summaryrefslogtreecommitdiff
path: root/Runtime/Animation/AnimationEvent.cpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Animation/AnimationEvent.cpp
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Animation/AnimationEvent.cpp')
-rw-r--r--Runtime/Animation/AnimationEvent.cpp202
1 files changed, 202 insertions, 0 deletions
diff --git a/Runtime/Animation/AnimationEvent.cpp b/Runtime/Animation/AnimationEvent.cpp
new file mode 100644
index 0000000..2613d11
--- /dev/null
+++ b/Runtime/Animation/AnimationEvent.cpp
@@ -0,0 +1,202 @@
+#include "UnityPrefix.h"
+#include "AnimationEvent.h"
+#include "Configuration/UnityConfigure.h"
+#include "Runtime/Mono/MonoBehaviour.h"
+#include "Runtime/Scripting/ScriptingUtility.h"
+#include "Runtime/Scripting/Backend/ScriptingArguments.h"
+#include "Runtime/Scripting/CommonScriptingClasses.h"
+#include "Runtime/Scripting/ScriptingManager.h"
+#include "Runtime/Scripting/Backend/ScriptingBackendApi.h"
+#include "Runtime/Scripting/Scripting.h"
+#include "Runtime/Scripting/ScriptingUtility.h"
+#include "Runtime/Scripting/ScriptingObjectWithIntPtrField.h"
+#include "Runtime/Misc/BuildSettings.h"
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+
+#if ENABLE_MONO
+#endif
+
+
+INSTANTIATE_TEMPLATE_TRANSFER_EXPORTED (AnimationEvent)
+
+template<class TransferFunction>
+void AnimationEvent::Transfer (TransferFunction& transfer)
+{
+ TRANSFER (time);
+ TRANSFER (functionName);
+ transfer.Transfer (stringParameter, "data");
+ transfer.Transfer (objectReferenceParameter, "objectReferenceParameter");
+ transfer.Transfer (floatParameter, "floatParameter");
+ transfer.Transfer (intParameter, "intParameter");
+
+ TRANSFER (messageOptions);
+}
+
+#if ENABLE_SCRIPTING
+
+
+static ScriptingObjectPtr s_ManagedAnimationEvent;
+
+static bool SetupInvokeArgument(ScriptingMethodPtr method, AnimationEvent& event, ScriptingArguments& parameters)
+{
+ int argCount = scripting_method_get_argument_count(method, GetScriptingTypeRegistry());
+
+ // Fast path - method takes no arguments
+ if (argCount == 0)
+ return true;
+
+ if (argCount > 1)
+ return false;
+
+ ScriptingTypePtr typeOfFirstArgument = scripting_method_get_nth_argumenttype(method,0,GetScriptingTypeRegistry());
+
+ const CommonScriptingClasses& cc = GetScriptingManager().GetCommonClasses();
+
+ if (typeOfFirstArgument == cc.floatSingle)
+ {
+ parameters.AddFloat(event.floatParameter);
+ return true;
+ }
+
+ if (typeOfFirstArgument == cc.int_32)
+ {
+ parameters.AddInt(event.intParameter);
+ return true;
+ }
+
+ if (typeOfFirstArgument == cc.string)
+ {
+ parameters.AddString(event.stringParameter.c_str());
+ return true;
+ }
+
+ if (typeOfFirstArgument == cc.animationEvent)
+ {
+ ScriptingObjectWithIntPtrField<AnimationEvent> scriptingAnimationEvent = scripting_object_new(GetScriptingManager().GetCommonClasses().animationEvent);
+ scriptingAnimationEvent.SetPtr(&event);
+
+ s_ManagedAnimationEvent = scriptingAnimationEvent.object;
+ parameters.AddObject(scriptingAnimationEvent.object);
+ return true;
+ }
+
+ if (scripting_class_is_subclass_of(typeOfFirstArgument,cc.unityEngineObject))
+ {
+ parameters.AddObject(Scripting::ScriptingWrapperFor(event.objectReferenceParameter));
+ return true;
+ }
+
+ if (scripting_class_is_enum(typeOfFirstArgument))
+ {
+ parameters.AddInt(event.intParameter);
+ return true;
+ }
+
+ return false;
+}
+
+static void CleanupManagedAnimationEventIfRequired()
+{
+ if (s_ManagedAnimationEvent == SCRIPTING_NULL)
+ return;
+
+ AnimationEvent* nativeAnimationEvent = NULL;
+ MarshallNativeStructIntoManaged(nativeAnimationEvent, s_ManagedAnimationEvent);
+ s_ManagedAnimationEvent = SCRIPTING_NULL;
+}
+
+static bool FireEventTo(MonoBehaviour& behaviour, AnimationEvent& event, AnimationState* state)
+{
+ ScriptingObjectPtr instance = behaviour.GetInstance ();
+ if (instance == SCRIPTING_NULL)
+ return false;
+
+ ScriptingMethodPtr method = behaviour.FindMethod (event.functionName.c_str());
+ if (method == SCRIPTING_NULL)
+ return false;
+
+
+ ScriptingInvocation invocation(method);
+
+ if (!SetupInvokeArgument(method, event, invocation.Arguments()))
+ {
+ ErrorStringObject (Format ("Failed to call AnimationEvent %s of class %s.\nThe function must have either 0 or 1 parameters and the parameter can only be: string, float, int, enum, Object and AnimationEvent.", scripting_method_get_name (method), behaviour.GetScriptClassName ().c_str ()), &behaviour);
+ return true;
+ }
+
+ // Suppress immediate destruction during the event callback to disallow
+ // the object killing itself directly or indirectly in there (would do bad
+ // things to the still updating animation state).
+ const bool disableImmediateDestruction = IS_CONTENT_NEWER_OR_SAME (kUnityVersion4_0_a1);
+ bool oldDisableImmediateDestruction = false;
+ if (disableImmediateDestruction)
+ {
+ oldDisableImmediateDestruction = GetDisableImmediateDestruction ();
+ SetDisableImmediateDestruction (true);
+ }
+
+ event.stateSender = state;
+
+ ScriptingExceptionPtr exception = NULL;
+ invocation.object = instance;
+ invocation.logException = true;
+ invocation.objectInstanceIDContextForException = behaviour.GetInstanceID();
+ ScriptingObjectPtr returnValue = invocation.Invoke();
+
+ if (disableImmediateDestruction)
+ SetDisableImmediateDestruction (oldDisableImmediateDestruction);
+
+ if (returnValue && exception == NULL)
+ behaviour.HandleCoroutineReturnValue (method, returnValue);
+
+ event.stateSender = NULL;
+ CleanupManagedAnimationEventIfRequired();
+
+ return true;
+}
+
+static bool EventRequiresReceiver(const AnimationEvent& event)
+{
+ return event.messageOptions == 0;
+}
+
+#endif
+
+bool FireEvent (AnimationEvent& event, AnimationState* state, Unity::Component& animation)
+{
+ #if ENABLE_SCRIPTING
+ GameObject& go = animation.GetGameObject();
+ if (!go.IsActive ())
+ return false;
+
+ bool sent = false;
+
+ for (int i=0;i<go.GetComponentCount ();i++)
+ {
+ if (go.GetComponentClassIDAtIndex (i) != ClassID (MonoBehaviour))
+ continue;
+
+ MonoBehaviour& behaviour = static_cast<MonoBehaviour&> (go.GetComponentAtIndex (i));
+ if (FireEventTo(behaviour,event,state))
+ sent = true;
+ }
+
+ if (DEPLOY_OPTIMIZED)
+ return true;
+
+ if (sent)
+ return true;
+
+ if (!EventRequiresReceiver(event))
+ return true;
+
+ std::string warning = event.functionName.empty()
+ ? Format ("'%s' AnimationEvent has no function name specified!", go.GetName())
+ : Format ("'%s' AnimationEvent '%s' has no receiver! Are you missing a component?", go.GetName(), event.functionName.c_str());
+
+ ErrorStringObject (warning.c_str(), animation.GetGameObjectPtr());
+ return true;
+ #else
+ return false;
+ #endif
+}