浏览代码

WIP: On-demand 3D viewport drawing
- On-demand drawing for scene axes
- Disable on-demand drawing in play-mode, animation preview and particle preview

BearishSun 6 年之前
父节点
当前提交
ec2410d51e

+ 22 - 10
Source/EditorManaged/General/EditorApplication.cs

@@ -247,6 +247,8 @@ namespace bs.Editor
         private static bool delayUnloadProject;
         private static Action delayUnloadCallback;
 
+        private static HashSet<string> onDemandDrawingDisablers = new HashSet<string>();
+
         #pragma warning disable 0414
         private static EditorApplication instance;
         #pragma warning restore 0414
@@ -284,25 +286,25 @@ namespace bs.Editor
                         log.Refresh();
                 }
 
-                ToggleOnDemandDrawing(false);
+                ToggleOnDemandDrawing("__PlayMode", false);
                 ToggleToolbarItem("Play", true);
             };
 
             PlayInEditor.OnStopped += () =>
             {
-                ToggleOnDemandDrawing(true);
+                ToggleOnDemandDrawing("__PlayMode", true);
                 ToggleToolbarItem("Play", false);
             };
 
             PlayInEditor.OnPaused += () =>
             {
-                ToggleOnDemandDrawing(true);
+                ToggleOnDemandDrawing("__PlayMode", true);
                 ToggleToolbarItem("Pause", true);
             };
 
             PlayInEditor.OnUnpaused += () =>
             {
-                ToggleOnDemandDrawing(false);
+                ToggleOnDemandDrawing("__PlayMode", false);
                 ToggleToolbarItem("Pause", false);
             };
 
@@ -880,18 +882,28 @@ namespace bs.Editor
         }
 
         /// <summary>
-        /// Enables or disables on-demand drawing for 3D viewports. When enabled the viewports will only be
-        /// redrawn when <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn
-        /// every frame.
+        /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
+        /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
+        /// Normally you always want to keep this disabled unless you know the viewport will require updates
+        /// every frame (e.g. when a game is running, or when previewing animations).
         /// </summary>
+        /// <param name="caller">Unique string describing the caller that's requesting on-demand drawing is enabled or
+        /// disabled. On-demand drawing will be enabled only if *all* callers enable it.</param>
         /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
-        public static void ToggleOnDemandDrawing(bool enabled)
+        public static void ToggleOnDemandDrawing(string caller, bool enabled)
         {
+            if (enabled)
+                onDemandDrawingDisablers.Remove(caller);
+            else
+                onDemandDrawingDisablers.Add(caller);
+
+            bool isEnabled = onDemandDrawingDisablers.Count == 0;
+
             SceneWindow sceneWindow = EditorWindow.GetWindow<SceneWindow>();
-            sceneWindow?.ToggleOnDemandDrawing(enabled);
+            sceneWindow?.ToggleOnDemandDrawing(isEnabled);
 
             GameWindow gameWindow = EditorWindow.GetWindow<GameWindow>();
-            gameWindow?.ToggleOnDemandDrawing(enabled);
+            gameWindow?.ToggleOnDemandDrawing(isEnabled);
         }
 
         /// <summary>

+ 3 - 0
Source/EditorManaged/Windows/AnimationWindow.cs

@@ -838,6 +838,7 @@ namespace bs.Editor
                 float time = guiCurveEditor.GetTimeForFrame(currentFrameIdx);
 
                 animation.EditorPlay(clipInfo.clip, time);
+                EditorApplication.ToggleOnDemandDrawing("__AnimationPreview", false);
             }
 
             playButton.Value = true;
@@ -849,6 +850,7 @@ namespace bs.Editor
         private void EndPlayback()
         {
             PreviewFrame(currentFrameIdx);
+            EditorApplication.ToggleOnDemandDrawing("__AnimationPreview", true);
             playButton.Value = false;
         }
 
@@ -868,6 +870,7 @@ namespace bs.Editor
                 animation.EditorPlay(clipInfo.clip, time, true);
 
             UpdateGenericCurves(time);
+            EditorApplication.NotifyNeedsRedraw();
         }
 
         /// <summary>

+ 2 - 0
Source/EditorManaged/Windows/GameWindow.cs

@@ -172,6 +172,8 @@ namespace bs.Editor
         /// <summary>
         /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
         /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
+        /// Normally you always want to keep this disabled unless you know the viewport will require updates
+        /// every frame (e.g. when a game is running, or when previewing animations).
         /// </summary>
         /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
         internal void ToggleOnDemandDrawing(bool enabled)

+ 1 - 0
Source/EditorManaged/Windows/Scene/Gizmos/ParticleSystemGizmos.cs

@@ -297,6 +297,7 @@ namespace bs.Editor
         [OnSelectionChanged]
         private static void SelectionChanged(ParticleSystem component, bool selected)
         {
+            EditorApplication.ToggleOnDemandDrawing("__ParticlesPreview", !selected);
             component.TogglePreviewMode(selected);
         }
     }

+ 26 - 2
Source/EditorManaged/Windows/Scene/SceneAxesGUI.cs

@@ -61,6 +61,7 @@ namespace bs.Editor
             camera.OrthoHeight = 2.0f;
             camera.RenderSettings.EnableHDR = false;
             camera.RenderSettings.EnableSkybox = false;
+            camera.Flags = CameraFlag.OnDemand;
 
             renderTextureGUI = new GUIRenderTexture(renderTexture, true);
 
@@ -79,6 +80,8 @@ namespace bs.Editor
 
             this.panel = panel;
             this.bounds = bounds;
+
+            NotifyNeedsRedraw();
         }
 
         /// <summary>
@@ -92,7 +95,8 @@ namespace bs.Editor
 
             pointerPos.x -= bounds.x;
             pointerPos.y -= bounds.y;
-            sceneHandles.TrySelect(pointerPos);
+            if(sceneHandles.TrySelect(pointerPos))
+                NotifyNeedsRedraw();
         }
 
         /// <summary>
@@ -110,6 +114,7 @@ namespace bs.Editor
         public void ClearSelection()
         {
             sceneHandles.ClearSelection();
+            NotifyNeedsRedraw();
         }
 
         /// <summary>
@@ -121,7 +126,8 @@ namespace bs.Editor
             pointerPos.x -= bounds.x;
             pointerPos.y -= bounds.y;
 
-            sceneHandles.UpdateInput(pointerPos, Input.PointerDelta);
+            if(sceneHandles.UpdateInput(pointerPos, Input.PointerDelta))
+                NotifyNeedsRedraw();
         }
 
         /// <summary>
@@ -132,6 +138,24 @@ namespace bs.Editor
             sceneHandles.Draw();
         }
 
+        /// <summary>
+        /// Notifies the system that the 3D viewport should be redrawn.
+        /// </summary>
+        internal void NotifyNeedsRedraw()
+        {
+            camera.NotifyNeedsRedraw();
+        }
+
+        /// <summary>
+        /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
+        /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
+        /// </summary>
+        /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
+        internal void ToggleOnDemandDrawing(bool enabled)
+        {
+            camera.Flags = enabled ? CameraFlag.OnDemand : new CameraFlag();
+        }
+
         /// <summary>
         /// Moves the GUI element to the specified position.
         /// </summary>

+ 20 - 11
Source/EditorManaged/Windows/Scene/SceneCamera.cs

@@ -73,6 +73,11 @@ namespace bs.Editor
         /// </summary>
         public Camera Camera { get => camera; }
 
+        /// <summary>
+        /// Counter that increments every frame when the camera transform changes.
+        /// </summary>
+        public ulong UpdateCount { get; private set; }
+
         /// <summary>
         /// Settings for controlling scene camera view.
         /// </summary>
@@ -177,23 +182,19 @@ namespace bs.Editor
         /// </summary>
         internal void NotifyNeedsRedraw()
         {
-            camera?.NotifyNeedsRedraw();
+            camera.NotifyNeedsRedraw();
         }
 
         /// <summary>
         /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
         /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
+        /// Normally you always want to keep this disabled unless you know the viewport will require updates
+        /// every frame (e.g. when a game is running, or when previewing animations).
         /// </summary>
         /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
         internal void ToggleOnDemandDrawing(bool enabled)
         {
-            if (camera == null)
-                return;
-
-            if (enabled)
-                camera.Flags = CameraFlag.OnDemand;
-            else
-                camera.Flags = new CameraFlag();
+            camera.Flags = enabled ? CameraFlag.OnDemand : new CameraFlag();
         }
 
         #endregion
@@ -228,6 +229,7 @@ namespace bs.Editor
             bool isOrthographic = camera.ProjectionType == ProjectionType.Orthographic;
             float frameDelta = Time.FrameDelta;
 
+            bool updated = false;
             if (inputEnabled)
             {
                 bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn);
@@ -318,7 +320,7 @@ namespace bs.Editor
                         SceneObject.Move(velocity * frameDelta);
                     }
 
-                    NotifyNeedsRedraw();
+                    updated = true;
                 }
 
                 // Pan
@@ -332,7 +334,7 @@ namespace bs.Editor
 
                     SceneObject.Move(direction * MoveSettings.panSpeed * frameDelta);
 
-                    NotifyNeedsRedraw();
+                    updated = true;
                 }
             }
             else
@@ -371,12 +373,18 @@ namespace bs.Editor
                                 camera.OrthoHeight = orthoHeight;
                         }
 
-                        NotifyNeedsRedraw();
+                        updated = true;
                     }
                 }
             }
 
             UpdateAnim();
+
+            if (updated)
+            {
+                NotifyNeedsRedraw();
+                UpdateCount++;
+            }
         }
 
         /// <summary>
@@ -492,6 +500,7 @@ namespace bs.Editor
             camera.FarClipPlane = far;
 
             NotifyNeedsRedraw();
+            UpdateCount++;
         }
 
         /// <summary>

+ 14 - 3
Source/EditorManaged/Windows/Scene/SceneWindow.cs

@@ -36,6 +36,7 @@ namespace bs.Editor
 
         private Camera camera;
         private SceneCamera sceneCamera;
+        private ulong cameraUpdateCount;
         private RenderTexture renderTexture;
         private GUILayoutY mainLayout;
         private GUIPanel rtPanel;
@@ -776,7 +777,7 @@ namespace bs.Editor
                 SceneHandles.EndInput();
             }
 
-            if(sceneHandles.IsActive())
+            if(handleActive)
                 NotifyNeedsRedraw();
 
             sceneHandles.Draw();
@@ -788,6 +789,12 @@ namespace bs.Editor
 
             UpdateGridMode();
 
+            if (cameraUpdateCount != sceneCamera.UpdateCount)
+            {
+                sceneAxesGUI.NotifyNeedsRedraw();
+                cameraUpdateCount = sceneCamera.UpdateCount;
+            }
+
             if (VirtualInput.IsButtonDown(frameKey))
                 sceneCamera.FrameSelected();
         }
@@ -1014,17 +1021,21 @@ namespace bs.Editor
         /// </summary>
         internal void NotifyNeedsRedraw()
         {
-            sceneCamera?.NotifyNeedsRedraw();
+            sceneCamera.NotifyNeedsRedraw();
+            sceneAxesGUI.NotifyNeedsRedraw();
         }
 
         /// <summary>
         /// Enables or disables on-demand drawing. When enabled the 3D viewport will only be redrawn when
         /// <see cref="NotifyNeedsRedraw"/> is called. If disabled the viewport will be redrawn every frame.
+        /// Normally you always want to keep this disabled unless you know the viewport will require updates
+        /// every frame (e.g. when a game is running, or when previewing animations).
         /// </summary>
         /// <param name="enabled">True to enable on-demand drawing, false otherwise.</param>
         internal void ToggleOnDemandDrawing(bool enabled)
         {
-            sceneCamera?.ToggleOnDemandDrawing(enabled);
+            sceneCamera.ToggleOnDemandDrawing(enabled);
+            sceneAxesGUI.ToggleOnDemandDrawing(enabled);
         }
 
         /// <summary>

+ 1 - 1
Source/bsf

@@ -1 +1 @@
-Subproject commit 2bd8a37787b988956afb0fb9662e3fc5a88aa3ad
+Subproject commit af66e8d9632c2dadfa13dcac74de8757ea46567a