فهرست منبع

Animation playback during edit mode for preview purposes (WIP)

BearishSun 9 سال پیش
والد
کامیت
8de834e01c

+ 1 - 1
Source/BansheeCore/Source/BsProfilerCPU.cpp

@@ -93,7 +93,7 @@ namespace BansheeEngine
 		__cpuid(a, b);
 		return __rdtsc();
 #else
-		static_assert("Unsupported compiler");
+		static_assert(false, "Unsupported compiler");
 #endif		
 	}
 

+ 1 - 6
Source/BansheeEditor/Source/BsProjectLibrary.cpp

@@ -820,12 +820,7 @@ namespace BansheeEngine
 			assetPath = path.getRelative(getResourcesFolder());
 		}
 
-		LibraryEntry* existingEntry = findEntry(assetPath);
-		if (existingEntry != nullptr)
-		{
-			LOGWRN("Resource already exists at the specified path : " + assetPath.toString() + ". Unable to save.");
-			return;
-		}
+		deleteEntry(assetPath);
 
 		resource->setName(path.getWFilename(false));
 

+ 1 - 1
Source/BansheeMono/Source/BsMonoManager.cpp

@@ -341,7 +341,7 @@ namespace BansheeEngine
 #if BS_PLATFORM == BS_PLATFORM_WIN32
 		compilerPath.append("mcs.exe");
 #else
-		static_assert("Not implemented");
+		static_assert(false, "Not implemented");
 #endif
 
 		return compilerPath;

+ 18 - 2
Source/MBansheeEditor/Windows/Animation/GUICurveEditor.cs

@@ -99,6 +99,7 @@ namespace BansheeEditor
         private bool isMousePressedOverKey;
         private bool isMousePressedOverTangent;
         private bool isDragInProgress;
+        private bool isModifiedDuringDrag;
         private List<DraggedKeyframes> draggedKeyframes = new List<DraggedKeyframes>();
         private TangentRef draggedTangent;
         private Vector2I dragStart;
@@ -128,6 +129,11 @@ namespace BansheeEditor
         /// </summary>
         public Action OnCurveModified;
 
+        /// <summary>
+        /// Triggered when the user clicks anywhere on the curve editor area.
+        /// </summary>
+        public Action OnClicked;
+
         /// <summary>
         /// The displayed range of the curve, where:
         ///   .x - Range of the horizontal area. Displayed area ranges from [0, x].
@@ -352,6 +358,12 @@ namespace BansheeEditor
             Rect2I elementBounds = GUIUtility.CalculateBounds(gui, window.GUI);
             Vector2I pointerPos = windowPos - new Vector2I(elementBounds.x, elementBounds.y);
 
+            bool isOverEditor = pointerPos.x >= 0 && pointerPos.x < width && pointerPos.y >= 0 && pointerPos.y < height;
+            if (!isOverEditor)
+                return;
+            else
+                OnClicked?.Invoke();
+
             Rect2I drawingBounds = drawingPanel.Bounds;
             Vector2I drawingPos = pointerPos - new Vector2I(drawingBounds.x, drawingBounds.y);
 
@@ -582,7 +594,7 @@ namespace BansheeEditor
                                     SelectKeyframe(new KeyframeRef(draggedEntry.curveIdx, keyframe.index));
                             }
 
-                            OnCurveModified?.Invoke();
+                            isModifiedDuringDrag = true;
                             guiCurveDrawing.Rebuild();
                             UpdateEventsGUI();
                         }
@@ -623,7 +635,7 @@ namespace BansheeEditor
                                 curve.KeyFrames[draggedTangent.keyframeRef.keyIdx] = keyframe;
                                 curve.Apply();
 
-                                OnCurveModified?.Invoke();
+                                isModifiedDuringDrag = true;
                                 guiCurveDrawing.Rebuild();
                             }
                         }
@@ -647,10 +659,14 @@ namespace BansheeEditor
         /// <param name="ev">Object containing pointer release event information.</param>
         internal void OnPointerReleased(PointerEvent ev)
         {
+            if (isModifiedDuringDrag)
+                OnCurveModified?.Invoke();
+
             isPointerHeld = false;
             isDragInProgress = false;
             isMousePressedOverKey = false;
             isMousePressedOverTangent = false;
+            isModifiedDuringDrag = false;
         }
 
         /// <summary>

+ 180 - 14
Source/MBansheeEditor/Windows/AnimationWindow.cs

@@ -64,10 +64,26 @@ namespace BansheeEditor
                 return;
 
             HandleDragAndZoomInput();
+
+            if (state == State.Playback)
+            {
+                Animation animation = selectedSO.GetComponent<Animation>();
+                if (animation != null)
+                {
+                    float time = animation.EditorGetTime();
+                    int frameIdx = (int)(time * fps);
+
+                    SetCurrentFrame(frameIdx);
+
+                    animation.UpdateFloatProperties();
+                }
+            }
         }
 
         private void OnDestroy()
         {
+            SwitchState(State.Normal);
+
             Selection.OnSelectionChanged -= OnSelectionChanged;
 
             if (selectedSO != null)
@@ -90,8 +106,8 @@ namespace BansheeEditor
         #endregion
 
         #region GUI
-        private GUIButton playButton;
-        private GUIButton recordButton;
+        private GUIToggle playButton;
+        private GUIToggle recordButton;
 
         private GUIButton prevFrameButton;
         private GUIIntField frameInputField;
@@ -162,8 +178,8 @@ namespace BansheeEditor
             GUIContent optionsIcon = new GUIContent(EditorBuiltin.GetLibraryWindowIcon(LibraryWindowIcon.Options),
                 new LocEdString("Options"));
 
-            playButton = new GUIButton(playIcon);
-            recordButton = new GUIButton(recordIcon);
+            playButton = new GUIToggle(playIcon, EditorStyles.Button);
+            recordButton = new GUIToggle(recordIcon, EditorStyles.Button);
 
             prevFrameButton = new GUIButton(prevFrameIcon);
             frameInputField = new GUIIntField();
@@ -174,39 +190,49 @@ namespace BansheeEditor
 
             optionsButton = new GUIButton(optionsIcon);
 
-            playButton.OnClick += () =>
+            playButton.OnToggled += x =>
             {
-                // TODO
-                // - Record current state of the scene object hierarchy
-                // - Evaluate all curves manually and update them
-                // - On end, restore original values of the scene object hierarchy
+                if(x)
+                    SwitchState(State.Playback);
+                else
+                    SwitchState(State.Normal);
             };
 
-            recordButton.OnClick += () =>
+            recordButton.OnToggled += x =>
             {
-                // TODO
-                // - Every frame read back current values of all the current curve's properties and assign it to the current frame
+                if (x)
+                    SwitchState(State.Recording);
+                else
+                    SwitchState(State.Normal);
             };
 
             prevFrameButton.OnClick += () =>
             {
+                SwitchState(State.Normal);
                 SetCurrentFrame(currentFrameIdx - 1);
             };
 
-            frameInputField.OnChanged += SetCurrentFrame;
+            frameInputField.OnChanged += x =>
+            {
+                SwitchState(State.Normal);
+                SetCurrentFrame(x);
+            };
 
             nextFrameButton.OnClick += () =>
             {
+                SwitchState(State.Normal);
                 SetCurrentFrame(currentFrameIdx + 1);
             };
 
             addKeyframeButton.OnClick += () =>
             {
+                SwitchState(State.Normal);
                 guiCurveEditor.AddKeyFrameAtMarker();
             };
 
             addEventButton.OnClick += () =>
             {
+                SwitchState(State.Normal);
                 guiCurveEditor.AddEventAtMarker();
             };
 
@@ -230,6 +256,8 @@ namespace BansheeEditor
                     fieldSelection.OnFieldSelected += OnFieldAdded;
                 };
 
+                SwitchState(State.Normal);
+
                 if (clipInfo.clip == null)
                 {
                     LocEdString title = new LocEdString("Warning");
@@ -284,6 +312,8 @@ namespace BansheeEditor
                 if (clipInfo.clip == null)
                     return;
 
+                SwitchState(State.Normal);
+
                 if (clipInfo.isImported)
                 {
                     LocEdString title = new LocEdString("Warning");
@@ -303,6 +333,7 @@ namespace BansheeEditor
                         if (x == DialogBox.ResultType.Yes)
                         {
                             RemoveSelectedFields();
+                            ApplyClipChanges();
                         }
                     });
                 }
@@ -373,7 +404,12 @@ namespace BansheeEditor
             guiCurveEditor.OnEventAdded += OnEventsChanged;
             guiCurveEditor.OnEventModified += EditorApplication.SetProjectDirty;
             guiCurveEditor.OnEventDeleted += OnEventsChanged;
-            guiCurveEditor.OnCurveModified += EditorApplication.SetProjectDirty;
+            guiCurveEditor.OnCurveModified += () =>
+            {
+                ApplyClipChanges();
+                EditorApplication.SetProjectDirty();
+            };
+            guiCurveEditor.OnClicked += () => SwitchState(State.Normal);
             guiCurveEditor.Redraw();
 
             horzScrollBar.SetWidth(curveEditorSize.x);
@@ -628,6 +664,15 @@ namespace BansheeEditor
             FPS = clipInfo.sampleRate;
         }
 
+        /// <summary>
+        /// Applies any changes made to the animation curves and events to the actual animation clip resource.
+        /// </summary>
+        private void ApplyClipChanges()
+        {
+            EditorAnimClipTangents unused;
+            clipInfo.Apply(out unused);
+        }
+
         /// <summary>
         /// Checks if the currently selected object has changed, and rebuilds the GUI and loads the animation clip if needed.
         /// </summary>
@@ -684,6 +729,126 @@ namespace BansheeEditor
         #endregion
 
         #region Record/Playback
+
+        /// <summary>
+        /// Possible states the animation window can be in.
+        /// </summary>
+        private enum State
+        {
+            Normal,
+            Recording,
+            Playback
+        }
+
+        private State state = State.Normal;
+
+        /// <summary>
+        /// Transitions the window into a different state. Caller must validate state transitions.
+        /// </summary>
+        /// <param name="state">New state to transition to.</param>
+        private void SwitchState(State state)
+        {
+            switch (this.state)
+            {
+                case State.Normal:
+                {
+                    switch (state)
+                    {
+                        case State.Playback:
+                            StartPlayback();
+                        break;
+                        case State.Recording:
+                            StartRecord();
+                        break;
+                    }
+                }
+                    break;
+                case State.Playback:
+                {
+                    switch (state)
+                    {
+                        case State.Normal:
+                            EndPlayback();
+                        break;
+                        case State.Recording:
+                            EndPlayback();
+                            StartRecord();
+                        break;
+                    }
+                }
+                    break;
+                case State.Recording:
+                {
+                    switch (state)
+                    {
+                        case State.Normal:
+                            EndRecord();
+                        break;
+                        case State.Playback:
+                            EndRecord();
+                            StartPlayback();
+                        break;
+                    }
+                }
+                    break;
+            }
+
+            this.state = state;
+        }
+
+        /// <summary>
+        /// Plays back the animation on the currently selected object.
+        /// </summary>
+        private void StartPlayback()
+        {
+            EditorAnimClipTangents unused;
+            clipInfo.Apply(out unused);
+
+            Animation animation = selectedSO.GetComponent<Animation>();
+            if (animation != null)
+            {
+                float time = guiCurveEditor.GetTimeForFrame(currentFrameIdx);
+
+                animation.EditorPlay(clipInfo.clip, time);
+            }
+
+            playButton.Value = true;
+        }
+
+        /// <summary>
+        /// Ends playback started with <see cref="StartPlayback"/>
+        /// </summary>
+        private void EndPlayback()
+        {
+            Animation animation = selectedSO.GetComponent<Animation>();
+            if (animation != null)
+                animation.EditorStop();
+
+            playButton.Value = false;
+        }
+
+        /// <summary>
+        /// Start recording modifications made to the selected scene object.
+        /// </summary>
+        private void StartRecord()
+        {
+            // TODO
+
+            recordButton.Value = true;
+        }
+
+        /// <summary>
+        /// Stops recording modifications made to the selected scene object.
+        /// </summary>
+        private void EndRecord()
+        {
+            // TODO
+
+            // TODO - Lock selection while active? (Don't allow another object to become anim focus in order to allow modifications on anim children).
+
+            recordButton.Value = false;
+        }
+
         /// <summary>
         /// Iterates over all curve path fields and records their current state. If the state differs from the current
         /// curve values, new keyframes are added.
@@ -1390,6 +1555,7 @@ namespace BansheeEditor
             pathNoRoot = pathNoRoot.Substring(separatorIdx + 1, pathNoRoot.Length - separatorIdx - 1);
 
             AddNewField(pathNoRoot, type);
+            ApplyClipChanges();
         }
 
         /// <summary>

+ 2 - 1
Source/SBansheeEngine/Source/BsPlayInEditorManager.cpp

@@ -64,12 +64,14 @@ namespace BansheeEngine
 			}
 
 			setSystemsPauseState(false);
+			gAnimation().setPaused(false);
 		}
 			break;
 		case PlayInEditorState::Paused:
 		{
 			mFrameStepActive = false;
 			setSystemsPauseState(true);
+			gAnimation().setPaused(true);
 
 			if (oldState == PlayInEditorState::Stopped)
 			{
@@ -147,6 +149,5 @@ namespace BansheeEngine
 	{
 		gPhysics().setPaused(paused);
 		gAudio().setPaused(paused);
-		gAnimation().setPaused(paused);
 	}
 }