diff --git a/Source/Engine/Animations/AnimEvent.cpp b/Source/Engine/Animations/AnimEvent.cpp
deleted file mode 100644
index e46a99c62..000000000
--- a/Source/Engine/Animations/AnimEvent.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
-
-#include "AnimEvent.h"
-#include "Engine/Scripting/BinaryModule.h"
-#include "Engine/Scripting/Internal/ManagedSerialization.h"
-#include "Engine/Serialization/SerializationFwd.h"
-#include "Engine/Serialization/Serialization.h"
-
-AnimEvent::AnimEvent(const SpawnParams& params)
- : ScriptingObject(params)
-{
-}
-
-void AnimEvent::Serialize(SerializeStream& stream, const void* otherObj)
-{
- SERIALIZE_GET_OTHER_OBJ(AnimEvent);
-
-#if !COMPILE_WITHOUT_CSHARP
- // Handle C# objects data serialization
- if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
- {
- stream.JKEY("V");
- if (other)
- {
- ManagedSerialization::SerializeDiff(stream, GetOrCreateManagedInstance(), other->GetOrCreateManagedInstance());
- }
- else
- {
- ManagedSerialization::Serialize(stream, GetOrCreateManagedInstance());
- }
- }
-#endif
-
- // Handle custom scripting objects data serialization
- if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
- {
- stream.JKEY("D");
- _type.Module->SerializeObject(stream, this, other);
- }
-}
-
-void AnimEvent::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
-{
-#if !COMPILE_WITHOUT_CSHARP
- // Handle C# objects data serialization
- if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
- {
- auto* const v = SERIALIZE_FIND_MEMBER(stream, "V");
- if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
- {
- ManagedSerialization::Deserialize(v->value, GetOrCreateManagedInstance());
- }
- }
-#endif
-
- // Handle custom scripting objects data serialization
- if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
- {
- auto* const v = SERIALIZE_FIND_MEMBER(stream, "D");
- if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
- {
- _type.Module->DeserializeObject(v->value, this, modifier);
- }
- }
-}
-
-AnimContinuousEvent::AnimContinuousEvent(const SpawnParams& params)
- : AnimEvent(params)
-{
-}
diff --git a/Source/Engine/Animations/AnimEvent.h b/Source/Engine/Animations/AnimEvent.h
index 2028501ea..4ed7eab48 100644
--- a/Source/Engine/Animations/AnimEvent.h
+++ b/Source/Engine/Animations/AnimEvent.h
@@ -2,8 +2,7 @@
#pragma once
-#include "Engine/Scripting/ScriptingObject.h"
-#include "Engine/Core/ISerializable.h"
+#include "Engine/Scripting/SerializableScriptingObject.h"
#if USE_EDITOR
#include "Engine/Core/Math/Color.h"
#endif
@@ -14,7 +13,7 @@ class Animation;
///
/// The animation notification event triggered during animation playback.
///
-API_CLASS(Abstract) class FLAXENGINE_API AnimEvent : public ScriptingObject, public ISerializable
+API_CLASS(Abstract) class FLAXENGINE_API AnimEvent : public SerializableScriptingObject
{
DECLARE_SCRIPTING_TYPE(AnimEvent);
@@ -35,10 +34,6 @@ API_CLASS(Abstract) class FLAXENGINE_API AnimEvent : public ScriptingObject, pub
API_FUNCTION() virtual void OnEvent(AnimatedModel* actor, Animation* anim, float time, float deltaTime)
{
}
-
- // [ISerializable]
- void Serialize(SerializeStream& stream, const void* otherObj) override;
- void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
};
///
diff --git a/Source/Engine/Animations/Animations.cpp b/Source/Engine/Animations/Animations.cpp
index 3c80cadbe..7dd2834bf 100644
--- a/Source/Engine/Animations/Animations.cpp
+++ b/Source/Engine/Animations/Animations.cpp
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "Animations.h"
+#include "AnimEvent.h"
#include "Engine/Engine/Engine.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Level/Actors/AnimatedModel.h"
@@ -52,6 +53,16 @@ TaskGraphSystem* Animations::System = nullptr;
Delegate Animations::DebugFlow;
#endif
+AnimEvent::AnimEvent(const SpawnParams& params)
+ : SerializableScriptingObject(params)
+{
+}
+
+AnimContinuousEvent::AnimContinuousEvent(const SpawnParams& params)
+ : AnimEvent(params)
+{
+}
+
bool AnimationsService::Init()
{
Animations::System = New();
diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp
index 9ece58f2a..c22616cd5 100644
--- a/Source/Engine/Scripting/ScriptingObject.cpp
+++ b/Source/Engine/Scripting/ScriptingObject.cpp
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "ScriptingObject.h"
+#include "SerializableScriptingObject.h"
#include "Scripting.h"
#include "BinaryModule.h"
#include "Engine/Level/Actor.h"
@@ -10,12 +11,14 @@
#include "Engine/Content/Content.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Threading/ThreadLocal.h"
+#include "Engine/Serialization/SerializationFwd.h"
#include "ManagedCLR/MAssembly.h"
#include "ManagedCLR/MClass.h"
#include "ManagedCLR/MUtils.h"
#include "ManagedCLR/MField.h"
#include "ManagedCLR/MCore.h"
#include "Internal/InternalCalls.h"
+#include "Internal/ManagedSerialization.h"
#include "FlaxEngine.Gen.h"
#define ScriptingObject_unmanagedPtr "__unmanagedPtr"
@@ -24,6 +27,64 @@
// TODO: don't leak memory (use some kind of late manual GC for those wrapper objects)
Dictionary ScriptingObjectsInterfaceWrappers;
+SerializableScriptingObject::SerializableScriptingObject(const SpawnParams& params)
+ : ScriptingObject(params)
+{
+}
+
+void SerializableScriptingObject::Serialize(SerializeStream& stream, const void* otherObj)
+{
+ SERIALIZE_GET_OTHER_OBJ(SerializableScriptingObject);
+
+#if !COMPILE_WITHOUT_CSHARP
+ // Handle C# objects data serialization
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
+ {
+ stream.JKEY("V");
+ if (other)
+ {
+ ManagedSerialization::SerializeDiff(stream, GetOrCreateManagedInstance(), other->GetOrCreateManagedInstance());
+ }
+ else
+ {
+ ManagedSerialization::Serialize(stream, GetOrCreateManagedInstance());
+ }
+ }
+#endif
+
+ // Handle custom scripting objects data serialization
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
+ {
+ stream.JKEY("D");
+ _type.Module->SerializeObject(stream, this, other);
+ }
+}
+
+void SerializableScriptingObject::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
+{
+#if !COMPILE_WITHOUT_CSHARP
+ // Handle C# objects data serialization
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsManagedType))
+ {
+ auto* const v = SERIALIZE_FIND_MEMBER(stream, "V");
+ if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
+ {
+ ManagedSerialization::Deserialize(v->value, GetOrCreateManagedInstance());
+ }
+ }
+#endif
+
+ // Handle custom scripting objects data serialization
+ if (EnumHasAnyFlags(Flags, ObjectFlags::IsCustomScriptingType))
+ {
+ auto* const v = SERIALIZE_FIND_MEMBER(stream, "D");
+ if (v != stream.MemberEnd() && v->value.IsObject() && v->value.MemberCount() != 0)
+ {
+ _type.Module->DeserializeObject(v->value, this, modifier);
+ }
+ }
+}
+
ScriptingObject::ScriptingObject(const SpawnParams& params)
: _gcHandle(0)
, _type(params.Type)
diff --git a/Source/Engine/Scripting/SerializableScriptingObject.h b/Source/Engine/Scripting/SerializableScriptingObject.h
new file mode 100644
index 000000000..8cd20af0b
--- /dev/null
+++ b/Source/Engine/Scripting/SerializableScriptingObject.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
+
+#pragma once
+
+#include "Engine/Scripting/ScriptingObject.h"
+#include "Engine/Core/ISerializable.h"
+
+///
+/// Base class for scripting objects that contain in-built serialization via ISerializable interface.
+///
+API_CLASS() class FLAXENGINE_API SerializableScriptingObject : public ScriptingObject, public ISerializable
+{
+ DECLARE_SCRIPTING_TYPE(SerializableScriptingObject);
+
+ // [ISerializable]
+ void Serialize(SerializeStream& stream, const void* otherObj) override;
+ void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
+};