Procházet zdrojové kódy

Better check for primary animation when evaluating generic curves, to avoid evaluating the wrong clip

BearishSun před 9 roky
rodič
revize
bfbab908a5

+ 11 - 0
Source/BansheeCore/Include/BsAnimation.h

@@ -294,6 +294,17 @@ namespace BansheeEngine
 		/** Checks if any animation clips are currently playing. */
 		bool isPlaying() const;
 
+		/** Returns the total number of animation clips influencing this animation. */
+		UINT32 getNumClips() const;
+
+		/** 
+		 * Returns one of the animation clips influencing this animation. 
+		 *
+		 * @param[in]	idx		Sequential index of the animation clip to retrieve. In range [0, getNumClips()].
+		 * @return				Animation clip at the specified index, or null if the index is out of range.
+		 */
+		HAnimationClip getClip(UINT32 idx) const;
+
 		/** 
 		 * Retrieves detailed information about a currently playing animation clip. 
 		 *

+ 13 - 0
Source/BansheeCore/Source/BsAnimation.cpp

@@ -892,6 +892,19 @@ namespace BansheeEngine
 		mDirty |= AnimDirtyStateFlag::Value;
 	}
 
+	UINT32 Animation::getNumClips() const
+	{
+		return (UINT32)mClipInfos.size();
+	}
+
+	HAnimationClip Animation::getClip(UINT32 idx) const
+	{
+		if (idx >= (UINT32)mClipInfos.size())
+			return HAnimationClip();
+
+		return mClipInfos[idx].clip;
+	}
+
 	void Animation::triggerEvents(float lastFrameTime, float delta)
 	{
 		for (auto& clipInfo : mClipInfos)

+ 10 - 12
Source/MBansheeEngine/Animation/Animation.cs

@@ -109,6 +109,7 @@ namespace BansheeEngine
         [SerializeField] private SerializableData serializableData = new SerializableData();
 
         private FloatCurvePropertyInfo[] floatProperties;
+        private AnimationClip floatPropertyClip;
 
         /// <summary>
         /// Contains mapping for a suffix used by property paths used for curve identifiers, to their index and type.
@@ -148,10 +149,7 @@ namespace BansheeEngine
                 serializableData.defaultClip = value;
 
                 if (value != null && _native != null)
-                {
-                    RebuildFloatProperties(value);
                     _native.Play(value);
-                }
             }
         }
 
@@ -208,10 +206,7 @@ namespace BansheeEngine
         public void Play(AnimationClip clip)
         {
             if (_native != null)
-            {
-                RebuildFloatProperties(clip);
                 _native.Play(clip);
-            }
         }
 
         /// <summary>
@@ -476,10 +471,15 @@ namespace BansheeEngine
 
         private void OnUpdate()
         {
-            // TODO: There could currently be a mismatch between the serialized properties and the active animation clip
-            //  - Add PrimaryClip field to NativeAnimation, then compare to the active clip and update if needed
-            // TODO: If primary animation clip isn't playing, don't update float properties
-            //  - Add dirty flags to each curve value and don't update unless they changed
+            if (_native == null)
+                return;
+
+            AnimationClip primaryClip = _native.GetClip(0);
+            if (primaryClip != floatPropertyClip)
+            {
+                RebuildFloatProperties(primaryClip);
+                floatPropertyClip = primaryClip;
+            }
 
             // Apply values from generic float curves 
             foreach (var entry in floatProperties)
@@ -523,8 +523,6 @@ namespace BansheeEngine
             if (serializableData.defaultClip != null)
                 _native.Play(serializableData.defaultClip);
 
-            RebuildFloatProperties(serializableData.defaultClip);
-
             Renderable renderable = SceneObject.GetComponent<Renderable>();
             if (renderable == null)
                 return;

+ 16 - 0
Source/MBansheeEngine/Animation/Interop/NativeAnimation.cs

@@ -23,6 +23,11 @@ namespace BansheeEngine
             set { Internal_SetSpeed(mCachedPtr, value); }
         }
 
+        public int NumClips
+        {
+            get { return Internal_GetNumClips(mCachedPtr); }
+        }
+
         public Action<AnimationClip, string> OnEventTriggered;
 
         public void Play(AnimationClip clip)
@@ -83,6 +88,11 @@ namespace BansheeEngine
             return Internal_IsPlaying(mCachedPtr);
         }
 
+        public AnimationClip GetClip(int index)
+        {
+            return Internal_GetClip(mCachedPtr, index);
+        }
+
         public bool GetState(AnimationClip clip, out AnimationClipState state)
         {
             IntPtr clipPtr = IntPtr.Zero;
@@ -164,6 +174,12 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetState(IntPtr thisPtr, IntPtr clipPtr, ref AnimationClipState state);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetNumClips(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern AnimationClip Internal_GetClip(IntPtr thisPtr, int idx);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern bool Internal_GetGenericCurveValue(IntPtr thisPtr, int curveIdx, out float value);
     }

+ 3 - 0
Source/SBansheeEngine/Include/BsScriptAnimation.h

@@ -54,6 +54,9 @@ namespace BansheeEngine
 		static bool internal_GetState(ScriptAnimation* thisPtr, ScriptAnimationClip* clip, AnimationClipState* state);
 		static void internal_SetState(ScriptAnimation* thisPtr, ScriptAnimationClip* clip, AnimationClipState* state);
 
+		static UINT32 internal_GetNumClips(ScriptAnimation* thisPtr);
+		static MonoObject* internal_GetClip(ScriptAnimation* thisPtr, UINT32 idx);
+
 		static bool internal_GetGenericCurveValue(ScriptAnimation* thisPtr, UINT32 curveIdx, float* value);
 
 		typedef void(__stdcall *OnEventTriggeredThunkDef) (MonoObject*, MonoObject*, MonoString*, MonoException**);

+ 20 - 0
Source/SBansheeEngine/Source/BsScriptAnimation.cpp

@@ -47,6 +47,9 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetState", &ScriptAnimation::internal_GetState);
 		metaData.scriptClass->addInternalCall("Internal_SetState", &ScriptAnimation::internal_SetState);
 
+		metaData.scriptClass->addInternalCall("Internal_GetNumClips", &ScriptAnimation::internal_GetNumClips);
+		metaData.scriptClass->addInternalCall("Internal_GetClip", &ScriptAnimation::internal_GetClip);
+
 		metaData.scriptClass->addInternalCall("Internal_GetGenericCurveValue", &ScriptAnimation::internal_GetGenericCurveValue);
 
 		sOnEventTriggeredThunk = (OnEventTriggeredThunkDef)metaData.scriptClass->getMethod("Internal_OnEventTriggered", 2)->getThunk();
@@ -137,6 +140,23 @@ namespace BansheeEngine
 		return thisPtr->getInternal()->isPlaying();
 	}
 
+	UINT32 ScriptAnimation::internal_GetNumClips(ScriptAnimation* thisPtr)
+	{
+		return thisPtr->getInternal()->getNumClips();
+	}
+
+	MonoObject* ScriptAnimation::internal_GetClip(ScriptAnimation* thisPtr, UINT32 idx)
+	{
+		HAnimationClip clip = thisPtr->getInternal()->getClip(idx);
+		if (!clip.isLoaded())
+			return nullptr;
+
+		ScriptAnimationClip* scriptClip;
+		ScriptResourceManager::instance().getScriptResource(clip, &scriptClip, true);
+
+		return scriptClip->getManagedInstance();
+	}
+
 	bool ScriptAnimation::internal_GetState(ScriptAnimation* thisPtr, ScriptAnimationClip* clip, AnimationClipState* state)
 	{
 		HAnimationClip nativeClip;