Просмотр исходного кода

Finalized work on first pass of C# object serialization

Marko Pintera 12 лет назад
Родитель
Сommit
0b3309d5d5

+ 2 - 0
BansheeEngine/Include/BsApplication.h

@@ -31,6 +31,8 @@ namespace BansheeEngine
 			const CM::ViewportPtr& getPrimaryViewport() const;
 	private:
 		boost::signals::connection updateCallbackConn;
+		CM::DynLib* mMonoPlugin;
+		CM::DynLib* mSBansheeEnginePlugin;
 
 		void update();
 	};

+ 6 - 2
BansheeEngine/Source/BsApplication.cpp

@@ -19,6 +19,7 @@ using namespace CamelotFramework;
 namespace BansheeEngine
 {
 	Application::Application()
+		:mMonoPlugin(nullptr), mSBansheeEnginePlugin(nullptr)
 	{
 
 	}
@@ -55,8 +56,8 @@ namespace BansheeEngine
 
 		EngineGUI::startUp(cm_new<EngineGUI>());
 
-		CM::gApplication().loadPlugin("BansheeMono");
-		CM::gApplication().loadPlugin("SBansheeEngine"); // Scripting interface
+		CM::gApplication().loadPlugin("BansheeMono", &mMonoPlugin);
+		CM::gApplication().loadPlugin("SBansheeEngine", &mSBansheeEnginePlugin); // Scripting interface
 		
 		updateCallbackConn = CM::gApplication().mainLoopCallback.connect(boost::bind(&Application::update, this));
 	}
@@ -70,6 +71,9 @@ namespace BansheeEngine
 	{
 		CM::gApplication().mainLoopCallback.disconnect(updateCallbackConn);
 
+		CM::gApplication().unloadPlugin(mSBansheeEnginePlugin);
+		CM::gApplication().unloadPlugin(mMonoPlugin);
+
 		EngineGUI::shutDown();
 
 		DrawHelper3D::shutDown();

+ 6 - 1
CamelotCore/Include/CmApplication.h

@@ -68,7 +68,12 @@ namespace CamelotFramework
 			 *
 			 * @param	pluginName	Name of the plugin to load, without extension.
 			 */
-			void* loadPlugin(const String& pluginName);
+			void* loadPlugin(const String& pluginName, DynLib** library = nullptr);
+
+			/**
+			 * @brief	Unloads a plugin. 
+			 */
+			void unloadPlugin(DynLib* library);
 
 			/**
 			 * @brief	Called every frame by the main loop, after scene update and before rendering.

+ 21 - 5
CamelotCore/Source/CmApplication.cpp

@@ -198,7 +198,7 @@ namespace CamelotFramework
 		Platform::shutDown();
 	}
 
-	void* Application::loadPlugin(const String& pluginName)
+	void* Application::loadPlugin(const String& pluginName, DynLib** library)
 	{
 		String name = pluginName;
 #if CM_PLATFORM == CM_PLATFORM_LINUX
@@ -216,19 +216,35 @@ namespace CamelotFramework
 			name += ".dll";
 #endif
 
-		DynLib* library = gDynLibManager().load(name);
-
+		DynLib* loadedLibrary = gDynLibManager().load(name);
 		if(library != nullptr)
+			*library = loadedLibrary;
+
+		if(loadedLibrary != nullptr)
 		{
 			typedef void* (*LoadPluginFunc)();
 
-			LoadPluginFunc loadPluginFunc = (LoadPluginFunc)library->getSymbol("loadPlugin");
-			return loadPluginFunc();
+			LoadPluginFunc loadPluginFunc = (LoadPluginFunc)loadedLibrary->getSymbol("loadPlugin");
+
+			if(loadPluginFunc != nullptr)
+				return loadPluginFunc();
 		}
 
 		return nullptr;
 	}
 
+	void Application::unloadPlugin(DynLib* library)
+	{
+		typedef void (*UnloadPluginFunc)();
+
+		UnloadPluginFunc unloadPluginFunc = (UnloadPluginFunc)library->getSymbol("unloadPlugin");
+
+		if(unloadPluginFunc != nullptr)
+			unloadPluginFunc();
+
+		gDynLibManager().unload(library);
+	}
+
 	UINT64 Application::getAppWindowId()
 	{
 		if(!mPrimaryWindow)

+ 2 - 13
GameObjectSerialization.txt

@@ -4,20 +4,9 @@ TODO
  ---------------------------------------
 
 IMMEDIATE:
-ScriptSerializableObjectRTTI::onDeserializationEnded
- - Compare stored and new SerializableObjectInfo (if it even exists)
-   - Must ensure the object info instances match
-    - (I might also want to compare type class/struct status in case it changed)
- - Create new managed object instance
- - Fill out the class fields (those whose types match the new SerializableObjectInfo->mFields)
 
-ScriptSerializableArrayRTTI::onDeserializationEnded
- - Attempt to create new managed object instance
-
-Need Object & Array ScriptSerializableField classes
-ManagedComponent needs to create SerializableObject and return it in its RTTI
-
-When deserializing SerializableObjectInfo base classes references won't be held anywhere (they're only pointed to by mBaseClass which is a weak_pointer)
+setValue in ScriptSerializableObject & ScriptSerializableArray should check if value is null and if the field type isn't a value type (can't be null)
+ScriptSerializableArray::onDeserializationEnded doesn't create an array instance because I'm not sure how yet
 
 In ScriptEnginePlugin I am running RuntimeScriptObjects but never shutting it down - Right now its only for debug purposes
 

+ 1 - 1
SBansheeEngine/Include/BsManagedComponent.h

@@ -30,7 +30,7 @@ namespace BansheeEngine
 		/** Standard constructor.
         */
 		ManagedComponent(const CM::HSceneObject& parent, const CM::String& ns, const CM::String& typeName);
-		void construct();
+		void construct(MonoObject* object);
 
 		void onDestroyed();
 

+ 18 - 1
SBansheeEngine/Include/BsManagedComponentRTTI.h

@@ -4,6 +4,7 @@
 #include "CmRTTIType.h"
 #include "CmGameObjectRTTI.h"
 #include "BsManagedComponent.h"
+#include "BsScriptSerializableObject.h"
 
 namespace BansheeEngine
 {
@@ -30,21 +31,37 @@ namespace BansheeEngine
 			obj->mTypeName = val;
 		}
 
+		ScriptSerializableObjectPtr getObjectData(ManagedComponent* obj)
+		{
+			return boost::any_cast<ScriptSerializableObjectPtr>(obj->mRTTIData);
+		}
+
+		void setObjectData(ManagedComponent* obj, ScriptSerializableObjectPtr val)
+		{
+			obj->mRTTIData = val;
+		}
+
 	public:
 		ManagedComponentRTTI()
 		{
 			addPlainField("mNamespace", 0, &ManagedComponentRTTI::getNamespace, &ManagedComponentRTTI::setNamespace);
 			addPlainField("mTypename", 1, &ManagedComponentRTTI::getTypename, &ManagedComponentRTTI::setTypename);
+			addReflectablePtrField("mObjectData", 2, &ManagedComponentRTTI::getObjectData, &ManagedComponentRTTI::setObjectData);
 		}
 
 		void onSerializationStarted(CM::IReflectable* obj)
 		{
+			ManagedComponent* mc = static_cast<ManagedComponent*>(obj);
+
+			mc->mRTTIData = ScriptSerializableObject::create(mc->getManagedInstance());
 		}
 
 		virtual void onDeserializationEnded(CM::IReflectable* obj)
 		{
 			ManagedComponent* mc = static_cast<ManagedComponent*>(obj);
-			mc->construct();
+			ScriptSerializableObjectPtr serializableObject = boost::any_cast<ScriptSerializableObjectPtr>(mc->mRTTIData);
+
+			mc->construct(serializableObject->getManagedInstance());
 		}
 
 		virtual const CM::String& getRTTIName()

+ 4 - 1
SBansheeEngine/Include/BsScriptEnginePrerequisites.h

@@ -77,7 +77,9 @@ namespace BansheeEngine
 		TID_SerializableFieldDataDouble = 50025,
 		TID_SerializableFieldDataString = 50026,
 		TID_SerializableFieldDataResourceRef = 50027,
-		TID_SerializableFieldDataGameObjectRef = 50028
+		TID_SerializableFieldDataGameObjectRef = 50028,
+		TID_SerializableFieldDataObject = 50029,
+		TID_SerializableFieldDataArray = 50030
 	};
 
 	static const char* BansheeEngineAssemblyName = "MBansheeEngine";
@@ -86,6 +88,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<ScriptSerializableFieldKey> ScriptSerializableFieldKeyPtr;
 	typedef std::shared_ptr<ScriptSerializableFieldDataEntry> ScriptSerializableFieldDataEntryPtr;
 	typedef std::shared_ptr<ScriptSerializableTypeInfo> ScriptSerializableTypeInfoPtr;
+	typedef std::shared_ptr<ScriptSerializableTypeInfoObject> ScriptSerializableTypeInfoObjectPtr;
 	typedef std::shared_ptr<ScriptSerializableObject> ScriptSerializableObjectPtr;
 	typedef std::shared_ptr<ScriptSerializableArray> ScriptSerializableArrayPtr;
 	typedef std::shared_ptr<ScriptSerializableAssemblyInfo> ScriptSerializableAssemblyInfoPtr;

+ 2 - 0
SBansheeEngine/Include/BsScriptSerializableArray.h

@@ -15,6 +15,8 @@ namespace BansheeEngine
 		ScriptSerializableArray(const ConstructPrivately& dummy, const ScriptSerializableTypeInfoArrayPtr& typeInfo, MonoObject* managedInstance);
 		ScriptSerializableArray(const ConstructPrivately& dummy);
 
+		MonoObject* getManagedInstance() const { return mManagedInstance; }
+
 		static ScriptSerializableArrayPtr create(MonoObject* managedInstance, const ScriptSerializableTypeInfoArrayPtr& typeInfo);
 
 	protected:

+ 14 - 1
SBansheeEngine/Include/BsScriptSerializableArrayRTTI.h

@@ -3,6 +3,8 @@
 #include "BsScriptEnginePrerequisites.h"
 #include "CmRTTIType.h"
 #include "BsScriptSerializableArray.h"
+#include "BsRuntimeScriptObjects.h"
+#include "BsMonoManager.h"
 
 namespace BansheeEngine
 {
@@ -51,7 +53,18 @@ namespace BansheeEngine
 		{
 			ScriptSerializableArray* serializableObject = static_cast<ScriptSerializableArray*>(obj);
 
-			// TODO
+			uint32_t lengths[1] = { serializableObject->mNumElements };
+
+			MonoArray* newArray = mono_array_new_full(MonoManager::instance().getDomain(), 
+				nullptr, (uintptr_t*)lengths, nullptr); // TODO - Type is nullptr
+
+			serializableObject->mManagedInstance = (MonoObject*)newArray;
+
+			CM::UINT32 idx = 0;
+			for(auto& arrayEntry : serializableObject->mArrayEntries)
+			{
+				serializableObject->setFieldData(idx, arrayEntry);
+			}
 		}
 
 		virtual const CM::String& getRTTIName()

+ 34 - 0
SBansheeEngine/Include/BsScriptSerializableField.h

@@ -313,4 +313,38 @@ namespace BansheeEngine
 		static CM::RTTITypeBase* getRTTIStatic();
 		virtual CM::RTTITypeBase* getRTTI() const;
 	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldDataObject : public ScriptSerializableFieldData
+	{
+	public:
+		ScriptSerializableObjectPtr value;
+
+		void* getValue(const ScriptSerializableTypeInfoPtr& typeInfo);
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class ScriptSerializableFieldDataObjectRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldDataArray : public ScriptSerializableFieldData
+	{
+	public:
+		ScriptSerializableArrayPtr value;
+
+		void* getValue(const ScriptSerializableTypeInfoPtr& typeInfo);
+
+		/************************************************************************/
+		/* 								RTTI		                     		*/
+		/************************************************************************/
+
+	public:
+		friend class ScriptSerializableFieldDataArrayRTTI;
+		static CM::RTTITypeBase* getRTTIStatic();
+		virtual CM::RTTITypeBase* getRTTI() const;
+	};
 }

+ 58 - 0
SBansheeEngine/Include/BsScriptSerializableFieldRTTI.h

@@ -534,4 +534,62 @@ namespace BansheeEngine
 			return CM::cm_shared_ptr<ScriptSerializableFieldDataGameObjectRef>();
 		}
 	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldDataObjectRTTI : public CM::RTTIType<ScriptSerializableFieldDataObject, ScriptSerializableFieldData, ScriptSerializableFieldDataObjectRTTI>
+	{
+	private:
+		ScriptSerializableObjectPtr getValue(ScriptSerializableFieldDataObject* obj) { return obj->value; }
+		void setValue(ScriptSerializableFieldDataObject* obj, ScriptSerializableObjectPtr val) { obj->value = val; }
+
+	public:
+		ScriptSerializableFieldDataObjectRTTI()
+		{
+			addReflectablePtrField("mValue", 0, &ScriptSerializableFieldDataObjectRTTI::getValue, &ScriptSerializableFieldDataObjectRTTI::setValue);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "SerializableFieldDataObject";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableFieldDataObject;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return CM::cm_shared_ptr<ScriptSerializableFieldDataObject>();
+		}
+	};
+
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldDataArrayRTTI : public CM::RTTIType<ScriptSerializableFieldDataArray, ScriptSerializableFieldData, ScriptSerializableFieldDataArrayRTTI>
+	{
+	private:
+		ScriptSerializableArrayPtr getValue(ScriptSerializableFieldDataArray* obj) { return obj->value; }
+		void setValue(ScriptSerializableFieldDataArray* obj, ScriptSerializableArrayPtr val) { obj->value = val; }
+
+	public:
+		ScriptSerializableFieldDataArrayRTTI()
+		{
+			addReflectablePtrField("mValue", 0, &ScriptSerializableFieldDataArrayRTTI::getValue, &ScriptSerializableFieldDataArrayRTTI::setValue);
+		}
+
+		virtual const CM::String& getRTTIName()
+		{
+			static CM::String name = "SerializableFieldDataArray";
+			return name;
+		}
+
+		virtual CM::UINT32 getRTTIId()
+		{
+			return TID_SerializableFieldDataArray;
+		}
+
+		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
+		{
+			return CM::cm_shared_ptr<ScriptSerializableFieldDataArray>();
+		}
+	};
 }

+ 3 - 0
SBansheeEngine/Include/BsScriptSerializableObject.h

@@ -15,6 +15,9 @@ namespace BansheeEngine
 		ScriptSerializableObject(const ConstructPrivately& dummy, ScriptSerializableObjectInfoPtr objInfo, MonoObject* managedInstance);
 		ScriptSerializableObject(const ConstructPrivately& dummy);
 
+		MonoObject* getManagedInstance() const { return mManagedInstance; }
+		ScriptSerializableObjectInfoPtr getObjectInfo() const { return mObjInfo; }
+
 		static ScriptSerializableObjectPtr create(MonoObject* managedInstance);
 
 	protected:

+ 15 - 5
SBansheeEngine/Include/BsScriptSerializableObjectInfo.h

@@ -35,6 +35,8 @@ namespace BansheeEngine
 
 	class BS_SCR_BE_EXPORT ScriptSerializableTypeInfo : public CM::IReflectable
 	{
+	public:
+		virtual bool matches(const ScriptSerializableTypeInfoPtr& typeInfo) const = 0;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/
@@ -50,6 +52,8 @@ namespace BansheeEngine
 	public:
 		ScriptPrimitiveType mType;
 
+		bool matches(const ScriptSerializableTypeInfoPtr& typeInfo) const;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -64,6 +68,9 @@ namespace BansheeEngine
 	public:
 		CM::String mTypeNamespace;
 		CM::String mTypeName;
+		bool mValueType;
+
+		bool matches(const ScriptSerializableTypeInfoPtr& typeInfo) const;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/
@@ -80,6 +87,8 @@ namespace BansheeEngine
 		ScriptSerializableTypeInfoPtr mElementType;
 		CM::UINT32 mRank;
 
+		bool matches(const ScriptSerializableTypeInfoPtr& typeInfo) const;
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -89,7 +98,7 @@ namespace BansheeEngine
 		virtual CM::RTTITypeBase* getRTTI() const;
 	};
 
-	class BS_SCR_BE_EXPORT ScriptSerializableFieldInfo : public ScriptSerializableTypeInfo
+	class BS_SCR_BE_EXPORT ScriptSerializableFieldInfo : public CM::IReflectable
 	{
 	public:
 		ScriptSerializableFieldInfo();
@@ -103,6 +112,8 @@ namespace BansheeEngine
 
 		MonoField* mMonoField;
 
+		bool isSerializable() const { return ((CM::UINT32)mFlags & (CM::UINT32)ScriptFieldFlags::Serializable) != 0; }
+
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
@@ -117,8 +128,7 @@ namespace BansheeEngine
 	public:
 		ScriptSerializableObjectInfo();
 
-		CM::String mNamespace;
-		CM::String mTypeName;
+		ScriptSerializableTypeInfoObjectPtr mTypeInfo;
 		CM::UINT32 mTypeId;
 
 		MonoClass* mMonoClass;
@@ -126,10 +136,10 @@ namespace BansheeEngine
 		CM::UnorderedMap<CM::String, CM::UINT32>::type mFieldNameToId;
 		CM::UnorderedMap<CM::UINT32, std::shared_ptr<ScriptSerializableFieldInfo>>::type mFields;
 
-		std::weak_ptr<ScriptSerializableObjectInfo> mBaseClass;
+		std::shared_ptr<ScriptSerializableObjectInfo> mBaseClass;
 		CM::Vector<std::weak_ptr<ScriptSerializableObjectInfo>>::type mDerivedClasses;
 
-		CM::String getFullTypeName() const { return mNamespace + "." + mTypeName; }
+		CM::String getFullTypeName() const { return mTypeInfo->mTypeNamespace + "." + mTypeInfo->mTypeName; }
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 22 - 22
SBansheeEngine/Include/BsScriptSerializableObjectInfoRTTI.h

@@ -67,24 +67,14 @@ namespace BansheeEngine
 	class BS_SCR_BE_EXPORT ScriptSerializableObjectInfoRTTI : public CM::RTTIType<ScriptSerializableObjectInfo, CM::IReflectable, ScriptSerializableObjectInfoRTTI>
 	{
 	private:
-		CM::String& getNamespace(ScriptSerializableObjectInfo* obj)
+		ScriptSerializableTypeInfoObjectPtr getTypeInfo(ScriptSerializableObjectInfo* obj)
 		{
-			return obj->mNamespace;
-		}
-
-		void setNamespace(ScriptSerializableObjectInfo* obj, CM::String& val)
-		{
-			obj->mNamespace = val;
-		}
-
-		CM::String& getTypename(ScriptSerializableObjectInfo* obj)
-		{
-			return obj->mTypeName;
+			return obj->mTypeInfo;
 		}
 
-		void setTypename(ScriptSerializableObjectInfo* obj, CM::String& val)
+		void setTypeInfo(ScriptSerializableObjectInfo* obj, ScriptSerializableTypeInfoObjectPtr val)
 		{
-			obj->mTypeName = val;
+			obj->mTypeInfo = val;
 		}
 
 		CM::UINT32& getTypeId(ScriptSerializableObjectInfo* obj)
@@ -99,7 +89,7 @@ namespace BansheeEngine
 
 		ScriptSerializableObjectInfoPtr getBaseClass(ScriptSerializableObjectInfo* obj)
 		{
-			return obj->mBaseClass.lock();
+			return obj->mBaseClass;
 		}
 
 		void setBaseClass(ScriptSerializableObjectInfo* obj, ScriptSerializableObjectInfoPtr val)
@@ -128,12 +118,11 @@ namespace BansheeEngine
 	public:
 		ScriptSerializableObjectInfoRTTI()
 		{
-			addPlainField("mNamespace", 0, &ScriptSerializableObjectInfoRTTI::getNamespace, &ScriptSerializableObjectInfoRTTI::setNamespace);
-			addPlainField("mTypename", 1, &ScriptSerializableObjectInfoRTTI::getTypename, &ScriptSerializableObjectInfoRTTI::setTypename);
-			addPlainField("mTypeId", 2, &ScriptSerializableObjectInfoRTTI::getTypeId, &ScriptSerializableObjectInfoRTTI::setTypeId);
-			addReflectablePtrField("mBaseClass", 3, &ScriptSerializableObjectInfoRTTI::getBaseClass, &ScriptSerializableObjectInfoRTTI::setBaseClass);
+			addReflectablePtrField("mTypeInfo", 0, &ScriptSerializableObjectInfoRTTI::getTypeInfo, &ScriptSerializableObjectInfoRTTI::setTypeInfo);
+			addPlainField("mTypeId", 1, &ScriptSerializableObjectInfoRTTI::getTypeId, &ScriptSerializableObjectInfoRTTI::setTypeId);
+			addReflectablePtrField("mBaseClass", 2, &ScriptSerializableObjectInfoRTTI::getBaseClass, &ScriptSerializableObjectInfoRTTI::setBaseClass);
 
-			addReflectablePtrArrayField("mFields", 4, &ScriptSerializableObjectInfoRTTI::getSerializableFieldInfo, 
+			addReflectablePtrArrayField("mFields", 3, &ScriptSerializableObjectInfoRTTI::getSerializableFieldInfo, 
 				&ScriptSerializableObjectInfoRTTI::getSerializableFieldInfoArraySize, &ScriptSerializableObjectInfoRTTI::setSerializableFieldInfo, 
 				&ScriptSerializableObjectInfoRTTI::setSerializableFieldInfoArraySize);
 		}
@@ -220,7 +209,7 @@ namespace BansheeEngine
 
 		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
 		{
-			return CM::cm_shared_ptr<ScriptSerializableFieldInfo>();
+			CM_EXCEPT(CM::InvalidStateException, "Cannot instantiate an abstract class");
 		}
 	};
 
@@ -247,7 +236,7 @@ namespace BansheeEngine
 
 		virtual std::shared_ptr<CM::IReflectable> newRTTIObject()
 		{
-			return CM::cm_shared_ptr<ScriptSerializableTypeInfo>();
+			CM_EXCEPT(CM::InvalidStateException, "Cannot instantiate an abstract class");
 		}
 	};
 
@@ -310,11 +299,22 @@ namespace BansheeEngine
 			obj->mTypeName = val;
 		}
 
+		bool& getIsValueType(ScriptSerializableTypeInfoObject* obj)
+		{
+			return obj->mValueType;
+		}
+
+		void setIsValueType(ScriptSerializableTypeInfoObject* obj, bool& val)
+		{
+			obj->mValueType = val;
+		}
+
 	public:
 		ScriptSerializableTypeInfoObjectRTTI()
 		{
 			addPlainField("mTypeName", 0, &ScriptSerializableTypeInfoObjectRTTI::getTypeName, &ScriptSerializableTypeInfoObjectRTTI::setTypeName);
 			addPlainField("mTypeNamespace", 1, &ScriptSerializableTypeInfoObjectRTTI::getTypeNamespace, &ScriptSerializableTypeInfoObjectRTTI::setTypeNamespace);
+			addPlainField("mValueType", 2, &ScriptSerializableTypeInfoObjectRTTI::getIsValueType, &ScriptSerializableTypeInfoObjectRTTI::setIsValueType);
 		}
 
 		virtual const CM::String& getRTTIName()

+ 81 - 1
SBansheeEngine/Include/BsScriptSerializableObjectRTTI.h

@@ -2,7 +2,10 @@
 
 #include "BsScriptEnginePrerequisites.h"
 #include "CmRTTIType.h"
+#include "BsRuntimeScriptObjects.h"
 #include "BsScriptSerializableObject.h"
+#include "BsScriptSerializableField.h"
+#include "BsMonoClass.h"
 
 namespace BansheeEngine
 {
@@ -51,7 +54,84 @@ namespace BansheeEngine
 		{
 			ScriptSerializableObject* serializableObject = static_cast<ScriptSerializableObject*>(obj);
 			
-			// TODO
+			ScriptSerializableObjectInfoPtr storedObjInfo = serializableObject->getObjectInfo();
+			ScriptSerializableObjectInfoPtr currentObjInfo = nullptr;
+
+			// See if this type even still exists
+			if(!RuntimeScriptObjects::instance().getSerializableObjectInfo(storedObjInfo->mTypeInfo->mTypeNamespace, storedObjInfo->mTypeInfo->mTypeName, currentObjInfo))
+				return;
+
+			serializableObject->mManagedInstance = currentObjInfo->mMonoClass->createInstance();
+
+			auto findFieldInfoFromKey = [&] (CM::UINT16 typeId, CM::UINT16 fieldId, ScriptSerializableObjectInfoPtr objInfo, 
+				ScriptSerializableFieldInfoPtr& outFieldInfo, ScriptSerializableObjectInfoPtr &outObjInfo) -> bool
+			{
+				while(objInfo != nullptr)
+				{
+					if(objInfo->mTypeId == typeId)
+					{
+						auto iterFind = objInfo->mFields.find(fieldId);
+						if(iterFind != objInfo->mFields.end())
+						{
+							outFieldInfo = iterFind->second;
+							outObjInfo = objInfo;
+
+							return true;
+						}
+
+						return false;
+					}
+
+					objInfo = objInfo->mBaseClass;
+				}
+
+				return false;
+			};
+
+			auto findTypeNameMatchingFieldInfo = [&] (const ScriptSerializableFieldInfoPtr& fieldInfo, const ScriptSerializableObjectInfoPtr& fieldObjInfo, 
+				ScriptSerializableObjectInfoPtr objInfo) -> ScriptSerializableFieldInfoPtr
+			{
+				while(objInfo != nullptr)
+				{
+					if(objInfo->mTypeInfo->matches(fieldObjInfo->mTypeInfo))
+					{
+						auto iterFind = objInfo->mFieldNameToId.find(fieldInfo->mName);
+						if(iterFind != objInfo->mFieldNameToId.end())
+						{
+							auto iterFind2 = objInfo->mFields.find(iterFind->second);
+							if(iterFind2 != objInfo->mFields.end())
+							{
+								ScriptSerializableFieldInfoPtr foundField = iterFind2->second;
+								if(foundField->isSerializable())
+								{
+									if(fieldInfo->mTypeInfo->matches(foundField->mTypeInfo))
+										return foundField;
+								}
+							}
+						}
+
+						return nullptr;
+					}
+
+					objInfo = objInfo->mBaseClass;
+				}
+
+				return nullptr;
+			};
+
+			// Scan all fields and ensure the fields still exist
+			for(auto& fieldEntry : serializableObject->mFieldEntries)
+			{
+				ScriptSerializableFieldInfoPtr storedFieldEntry;
+				ScriptSerializableObjectInfoPtr storedFieldObjEntry;
+				
+				if(!findFieldInfoFromKey(fieldEntry->mKey->mTypeId, fieldEntry->mKey->mFieldId, storedObjInfo, storedFieldEntry, storedFieldObjEntry))
+					continue;
+
+				ScriptSerializableFieldInfoPtr matchingFieldInfo = findTypeNameMatchingFieldInfo(storedFieldEntry, storedFieldObjEntry, currentObjInfo);
+				if(matchingFieldInfo != nullptr)
+					serializableObject->setFieldData(matchingFieldInfo, fieldEntry->mValue);
+			}
 		}
 
 		virtual const CM::String& getRTTIName()

+ 8 - 8
SBansheeEngine/Source/BsManagedComponent.cpp

@@ -11,13 +11,6 @@ namespace BansheeEngine
 	ManagedComponent::ManagedComponent(const CM::HSceneObject& parent, const CM::String& ns, const CM::String& typeName)
 		:mManagedInstance(nullptr), mNamespace(ns), mTypeName(typeName)
 	{
-
-	}
-
-	void ManagedComponent::construct()
-	{
-		mFullTypeName = mNamespace + "." + mTypeName;
-
 		MonoClass* managedClass = MonoManager::instance().findClass(mNamespace, mTypeName);
 		if(managedClass == nullptr)
 		{
@@ -25,7 +18,14 @@ namespace BansheeEngine
 			return;
 		}
 
-		mManagedInstance = managedClass->createInstance();
+		construct(managedClass->createInstance());
+	}
+
+	void ManagedComponent::construct(MonoObject* object)
+	{
+		mFullTypeName = mNamespace + "." + mTypeName;
+
+		mManagedInstance = object;
 		mManagedHandle = mono_gchandle_new(mManagedInstance, false);
 	}
 

+ 16 - 8
SBansheeEngine/Source/BsRuntimeScriptObjects.cpp

@@ -1,11 +1,13 @@
 #include "BsRuntimeScriptObjects.h"
 #include "BsScriptResourceManager.h"
 #include "BsScriptGameObjectManager.h"
+#include "BsScriptSerializableObjectInfo.h"
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
 #include "BsMonoClass.h"
 #include "BsMonoField.h"
 #include "BsMonoUtil.h"
+#include "CmRTTIType.h"
 
 using namespace CamelotFramework;
 
@@ -49,15 +51,19 @@ namespace BansheeEngine
 		{
 			if((curClass->isSubClassOf(mComponentClass) || curClass->hasAttribute(mSerializableAttribute)) && curClass != mComponentClass)
 			{
-				std::shared_ptr<ScriptSerializableObjectInfo> objInfo = cm_shared_ptr<ScriptSerializableObjectInfo>();
+				ScriptSerializableTypeInfoPtr typeInfo = determineType(curClass);
+				if(rtti_is_of_type<ScriptSerializableTypeInfoObject>(typeInfo))
+				{
+					std::shared_ptr<ScriptSerializableObjectInfo> objInfo = cm_shared_ptr<ScriptSerializableObjectInfo>();
+
+					objInfo->mTypeId = mUniqueTypeId++;
 
-				objInfo->mTypeId = mUniqueTypeId++;
-				objInfo->mTypeName = curClass->getTypeName();
-				objInfo->mNamespace = curClass->getNamespace();
-				objInfo->mMonoClass = curClass;
+					objInfo->mTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoObject>(typeInfo);
+					objInfo->mMonoClass = curClass;
 
-				assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
-				assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
+					assemblyInfo->mTypeNameToId[objInfo->getFullTypeName()] = objInfo->mTypeId;
+					assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
+				}
 			}
 		}
 
@@ -66,7 +72,7 @@ namespace BansheeEngine
 		{
 			std::shared_ptr<ScriptSerializableObjectInfo> objInfo = curClassInfo.second;
 
-			String fullTypeName = objInfo->mNamespace + "." + objInfo->mTypeName;
+			String fullTypeName = objInfo->getFullTypeName();
 			assemblyInfo->mTypeNameToId[fullTypeName] = objInfo->mTypeId;
 			assemblyInfo->mObjectInfos[objInfo->mTypeId] = objInfo;
 
@@ -249,6 +255,7 @@ namespace BansheeEngine
 					std::shared_ptr<ScriptSerializableTypeInfoObject> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoObject>();
 					typeInfo->mTypeNamespace = monoClass->getNamespace();
 					typeInfo->mTypeName = monoClass->getTypeName();
+					typeInfo->mValueType = false;
 
 					return typeInfo;
 				}
@@ -265,6 +272,7 @@ namespace BansheeEngine
 				std::shared_ptr<ScriptSerializableTypeInfoObject> typeInfo = cm_shared_ptr<ScriptSerializableTypeInfoObject>();
 				typeInfo->mTypeNamespace = monoClass->getNamespace();
 				typeInfo->mTypeName = monoClass->getTypeName();
+				typeInfo->mValueType = true;
 
 				return typeInfo;
 			}

+ 12 - 2
SBansheeEngine/Source/BsScriptEnginePlugin.cpp

@@ -1,9 +1,9 @@
 #include "BsScriptEnginePrerequisites.h"
 #include "BsMonoManager.h"
 #include "BsMonoAssembly.h"
-
-// DEBUG ONLY
 #include "BsRuntimeScriptObjects.h"
+#include "BsScriptResourceManager.h"
+#include "BsScriptGameObjectManager.h"
 
 using namespace CamelotFramework;
 
@@ -24,8 +24,18 @@ namespace BansheeEngine
 		MonoManager::instance().loadAssembly(ENGINE_ASSEMBLY_PATH, ENGINE_ASSEMBLY_NAME, ASSEMBLY_ENTRY_POINT);
 
 		RuntimeScriptObjects::startUp(cm_new<RuntimeScriptObjects>());
+		ScriptResourceManager::startUp(cm_new<ScriptResourceManager>());
+		ScriptGameObjectManager::startUp(cm_new<ScriptGameObjectManager>());
+
 		RuntimeScriptObjects::instance().refreshScriptObjects(BansheeEngineAssemblyName);
 
 		return nullptr;
 	}
+
+	extern "C" BS_SCR_BE_EXPORT void unloadPlugin()
+	{
+		ScriptGameObjectManager::shutDown();
+		ScriptResourceManager::shutDown();
+		RuntimeScriptObjects::shutDown();
+	}
 }

+ 66 - 0
SBansheeEngine/Source/BsScriptSerializableField.cpp

@@ -9,6 +9,8 @@
 #include "BsScriptSpriteTexture.h"
 #include "BsScriptSceneObject.h"
 #include "BsScriptComponent.h"
+#include "BsScriptSerializableObject.h"
+#include "BsScriptSerializableArray.h"
 
 using namespace CamelotFramework;
 
@@ -176,6 +178,26 @@ namespace BansheeEngine
 				}
 			}
 		}
+		else if(typeInfo->getTypeId() == TID_SerializableTypeInfoObject)
+		{
+			auto fieldData = cm_shared_ptr<ScriptSerializableFieldDataObject>();
+			if(value != nullptr)
+			{
+				fieldData->value = ScriptSerializableObject::create((MonoObject*)value);
+			}
+
+			return fieldData;
+		}
+		else if(typeInfo->getTypeId() == TID_SerializableTypeInfoArray)
+		{
+			auto fieldData = cm_shared_ptr<ScriptSerializableFieldDataArray>();
+			if(value != nullptr)
+			{
+				fieldData->value = ScriptSerializableArray::create((MonoObject*)value, std::static_pointer_cast<ScriptSerializableTypeInfoArray>(typeInfo));
+			}
+
+			return fieldData;
+		}
 
 		return nullptr;
 	}
@@ -392,6 +414,30 @@ namespace BansheeEngine
 		CM_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
 	}
 
+	void* ScriptSerializableFieldDataObject::getValue(const ScriptSerializableTypeInfoPtr& typeInfo)
+	{
+		if(typeInfo->getTypeId() == TID_SerializableTypeInfoObject)
+		{
+			auto objectTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoObject>(typeInfo);
+
+			return value->getManagedInstance();
+		}
+
+		CM_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
+	void* ScriptSerializableFieldDataArray::getValue(const ScriptSerializableTypeInfoPtr& typeInfo)
+	{
+		if(typeInfo->getTypeId() == TID_SerializableTypeInfoArray)
+		{
+			auto objectTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoArray>(typeInfo);
+
+			return value->getManagedInstance();
+		}
+
+		CM_EXCEPT(InvalidParametersException, "Requesting an invalid type in serializable field.");
+	}
+
 	RTTITypeBase* ScriptSerializableFieldKey::getRTTIStatic()
 	{
 		return ScriptSerializableFieldKeyRTTI::instance();
@@ -571,4 +617,24 @@ namespace BansheeEngine
 	{
 		return ScriptSerializableFieldDataGameObjectRef::getRTTIStatic();
 	}
+
+	RTTITypeBase* ScriptSerializableFieldDataObject::getRTTIStatic()
+	{
+		return ScriptSerializableFieldDataObjectRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldDataObject::getRTTI() const
+	{
+		return ScriptSerializableFieldDataObject::getRTTIStatic();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldDataArray::getRTTIStatic()
+	{
+		return ScriptSerializableFieldDataArrayRTTI::instance();
+	}
+
+	RTTITypeBase* ScriptSerializableFieldDataArray::getRTTI() const
+	{
+		return ScriptSerializableFieldDataArray::getRTTIStatic();
+	}
 }

+ 10 - 5
SBansheeEngine/Source/BsScriptSerializableObject.cpp

@@ -23,8 +23,12 @@ namespace BansheeEngine
 		UINT32 numFields = 0;
 		while(curType != nullptr)
 		{
-			numFields += (UINT32)mObjInfo->mFields.size();
-			curType = curType->mBaseClass.lock();
+			for(auto& field : mObjInfo->mFields)
+			{
+				if(field.second->isSerializable())
+					numFields++;
+			}
+			curType = curType->mBaseClass;
 		}
 
 		mFieldEntries.resize(numFields);
@@ -32,10 +36,11 @@ namespace BansheeEngine
 		UINT32 curIdx = 0;
 		while(curType != nullptr)
 		{
-			numFields += (UINT32)mObjInfo->mFields.size();
-
 			for(auto& field : mObjInfo->mFields)
 			{
+				if(!field.second->isSerializable())
+					continue;
+
 				ScriptSerializableFieldKeyPtr fieldKey = ScriptSerializableFieldKey::create(curType->mTypeId, field.second->mFieldId);
 				ScriptSerializableFieldDataPtr fieldData = getFieldData(field.second);
 
@@ -43,7 +48,7 @@ namespace BansheeEngine
 				curIdx++;
 			}
 
-			curType = curType->mBaseClass.lock();
+			curType = curType->mBaseClass;
 		}
 	}
 

+ 30 - 0
SBansheeEngine/Source/BsScriptSerializableObjectInfo.cpp

@@ -67,6 +67,16 @@ namespace BansheeEngine
 		return ScriptSerializableTypeInfo::getRTTIStatic();
 	}
 
+	bool ScriptSerializableTypeInfoPrimitive::matches(const ScriptSerializableTypeInfoPtr& typeInfo) const
+	{
+		if(!rtti_is_of_type<ScriptSerializableTypeInfoPrimitive>(typeInfo))
+			return false;
+
+		auto primTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoPrimitive>(typeInfo);
+
+		return primTypeInfo->mType == mType;
+	}
+
 	RTTITypeBase* ScriptSerializableTypeInfoPrimitive::getRTTIStatic()
 	{
 		return ScriptSerializableTypeInfoPrimitiveRTTI::instance();
@@ -77,6 +87,16 @@ namespace BansheeEngine
 		return ScriptSerializableTypeInfoPrimitive::getRTTIStatic();
 	}
 
+	bool ScriptSerializableTypeInfoObject::matches(const ScriptSerializableTypeInfoPtr& typeInfo) const
+	{
+		if(!rtti_is_of_type<ScriptSerializableTypeInfoObject>(typeInfo))
+			return false;
+
+		auto objTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoObject>(typeInfo);
+
+		return objTypeInfo->mTypeNamespace == mTypeNamespace && objTypeInfo->mTypeName == mTypeName;
+	}
+
 	RTTITypeBase* ScriptSerializableTypeInfoObject::getRTTIStatic()
 	{
 		return ScriptSerializableTypeInfoObjectRTTI::instance();
@@ -87,6 +107,16 @@ namespace BansheeEngine
 		return ScriptSerializableTypeInfoObject::getRTTIStatic();
 	}
 
+	bool ScriptSerializableTypeInfoArray::matches(const ScriptSerializableTypeInfoPtr& typeInfo) const
+	{
+		if(!rtti_is_of_type<ScriptSerializableTypeInfoArray>(typeInfo))
+			return false;
+
+		auto arrayTypeInfo = std::static_pointer_cast<ScriptSerializableTypeInfoArray>(typeInfo);
+
+		return arrayTypeInfo->mRank == mRank && arrayTypeInfo->mElementType->matches(mElementType);
+	}
+
 	RTTITypeBase* ScriptSerializableTypeInfoArray::getRTTIStatic()
 	{
 		return ScriptSerializableTypeInfoArrayRTTI::instance();