Browse Source

Feature: Added a class to easily serialize the current state of scene object hierarchy, and restore it later

BearishSun 6 years ago
parent
commit
200834da77

+ 2 - 0
Source/EditorCore/CMakeSources.cmake

@@ -33,6 +33,7 @@ set(BS_BANSHEEEDITOR_INC_SCENE
 	"Scene/BsScenePicking.h"
 	"Scene/BsScenePicking.h"
 	"Scene/BsSelection.h"
 	"Scene/BsSelection.h"
 	"Scene/BsSelectionRenderer.h"
 	"Scene/BsSelectionRenderer.h"
+	"Scene/BsSerializedSceneObject.h"
 )
 )
 
 
 set(BS_BANSHEEEDITOR_SRC_GUI
 set(BS_BANSHEEEDITOR_SRC_GUI
@@ -150,6 +151,7 @@ set(BS_BANSHEEEDITOR_SRC_SCENE
 	"Scene/BsSelection.cpp"
 	"Scene/BsSelection.cpp"
 	"Scene/BsScenePicking.cpp"
 	"Scene/BsScenePicking.cpp"
 	"Scene/BsSceneGrid.cpp"
 	"Scene/BsSceneGrid.cpp"
+	"Scene/BsSerializedSceneObject.cpp"
 )
 )
 
 
 set(BS_BANSHEEEDITOR_INC_NOFILTER
 set(BS_BANSHEEEDITOR_INC_NOFILTER

+ 111 - 0
Source/EditorCore/Scene/BsSerializedSceneObject.cpp

@@ -0,0 +1,111 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2019 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "Scene/BsSerializedSceneObject.h"
+#include "Scene/BsSceneObject.h"
+#include "Serialization/BsMemorySerializer.h"
+#include "Utility/BsUtility.h"
+
+namespace bs
+{
+	SerializedSceneObject::SerializedSceneObject(const HSceneObject& sceneObject, bool hierarchy)
+		:mSceneObject(sceneObject), mRecordHierarchy(hierarchy)
+	{
+		if(mSceneObject.isDestroyed())
+			return;
+
+		UINT32 numChildren = mSceneObject->getNumChildren();
+		HSceneObject* children = nullptr;
+
+		if (!mRecordHierarchy)
+		{
+			children = bs_stack_new<HSceneObject>(numChildren);
+			for (UINT32 i = 0; i < numChildren; i++)
+			{
+				HSceneObject child = mSceneObject->getChild(i);
+				children[i] = child;
+
+				child->setParent(HSceneObject());
+			}
+		}
+
+		bool isInstantiated = !mSceneObject->hasFlag(SOF_DontInstantiate);
+		mSceneObject->_setFlags(SOF_DontInstantiate);
+
+		MemorySerializer serializer;
+		mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize);
+
+		if (isInstantiated)
+			mSceneObject->_unsetFlags(SOF_DontInstantiate);
+
+		mSceneObjectProxy = EditorUtility::createProxy(mSceneObject);
+
+		HSceneObject parent = sceneObject->getParent();
+		if (parent != nullptr)
+			mSerializedObjectParentId = parent->getInstanceId();
+
+		if (!mRecordHierarchy)
+		{
+			for (UINT32 i = 0; i < numChildren; i++)
+				children[i]->setParent(sceneObject->getHandle());
+
+			bs_stack_delete(children, numChildren);
+		}
+	}
+
+	SerializedSceneObject::~SerializedSceneObject()
+	{
+		if (mSerializedObject != nullptr)
+		{
+			bs_free(mSerializedObject);
+			mSerializedObject = nullptr;
+		}
+	}
+
+	void SerializedSceneObject::restore()
+	{
+		HSceneObject parent;
+		if (mSerializedObjectParentId != 0)
+			parent = static_object_cast<SceneObject>(GameObjectManager::instance().getObject(mSerializedObjectParentId));
+
+
+		HSceneObject* children = nullptr;
+		UINT32 numChildren = 0;
+		if (!mSceneObject.isDestroyed())
+		{
+			numChildren = mSceneObject->getNumChildren();
+			if (!mRecordHierarchy)
+			{
+				children = bs_stack_new<HSceneObject>(numChildren);
+				for (UINT32 i = 0; i < numChildren; i++)
+				{
+					HSceneObject child = mSceneObject->getChild(i);
+					children[i] = child;
+
+					child->setParent(HSceneObject());
+				}
+			}
+
+			mSceneObject->destroy(true);
+		}
+
+		CoreSerializationContext serzContext;
+		serzContext.goState = bs_shared_ptr_new<GameObjectDeserializationState>(GODM_RestoreExternal | GODM_UseNewIds);
+
+		MemorySerializer serializer;
+		SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(
+			serializer.decode(mSerializedObject, mSerializedObjectSize, &serzContext));
+
+		EditorUtility::restoreIds(restored->getHandle(), mSceneObjectProxy);
+		restored->setParent(parent);
+
+		if (children)
+		{
+			for (UINT32 i = 0; i < numChildren; i++)
+				children[i]->setParent(restored->getHandle());
+
+			bs_stack_delete(children, numChildren);
+		}
+
+		restored->_instantiate();
+	}
+}

+ 53 - 0
Source/EditorCore/Scene/BsSerializedSceneObject.h

@@ -0,0 +1,53 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2019 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "Utility/BsEditorUtility.h"
+
+namespace bs
+{
+	/** @addtogroup Utility-Editor
+	*  @{
+	*/
+
+	/**
+	 * Serializes the current state of a scene object and allows that state to be restored. The advantage of using this 
+	 * class versus normal serialization is that the deserialization happens into the original scene object, instead of
+	 * creating a new scene object.
+	 */
+	class BS_ED_EXPORT BS_SCRIPT_EXPORT(m:Utility-Editor,api:bed) SerializedSceneObject final
+	{
+	public:
+		/**
+		 * Serializes the current state of the provided scene object.
+		 *
+		 * @param[in]	sceneObject		Object whose state to serialize.
+		 * @param[in]	hierarchy		If true all children of the provided scene object will be serialized as well,
+		 *								otherwise just the provided object will.
+		 */
+		BS_SCRIPT_EXPORT()
+		SerializedSceneObject(const HSceneObject& sceneObject, bool hierarchy = false);
+		~SerializedSceneObject();
+
+		/**
+		 * Restores the scene object to the state as it was when this object was created. If the scene object was deleted
+		 * since it will be resurrected.
+		 */
+		BS_SCRIPT_EXPORT()
+		void restore();
+
+	private:
+		friend class UndoRedo;
+
+		HSceneObject mSceneObject;
+		EditorUtility::SceneObjProxy mSceneObjectProxy;
+		bool mRecordHierarchy;
+
+		UINT8* mSerializedObject = nullptr;
+		UINT32 mSerializedObjectSize = 0;
+		UINT64 mSerializedObjectParentId = 0;
+	};
+
+	/** @} */
+}

+ 51 - 0
Source/EditorManaged/Generated/SerializedSceneObject.generated.cs

@@ -0,0 +1,51 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//************** Copyright (c) 2016-2019 Marko Pintera ([email protected]). All rights reserved. *******************//
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using bs;
+
+namespace bs.Editor
+{
+	/** @addtogroup Utility-Editor
+	 *  @{
+	 */
+
+	/// <summary>
+	/// Serializes the current state of a scene object and allows that state to be restored. The advantage of using this  
+	/// class versus normal serialization is that the deserialization happens into the original scene object, instead of 
+	/// creating a new scene object.
+	/// </summary>
+	[ShowInInspector]
+	public partial class SerializedSceneObject : ScriptObject
+	{
+		private SerializedSceneObject(bool __dummy0) { }
+		protected SerializedSceneObject() { }
+
+		/// <summary>Serializes the current state of the provided scene object.</summary>
+		/// <param name="sceneObject">Object whose state to serialize.</param>
+		/// <param name="hierarchy">
+		/// If true all children of the provided scene object will be serialized as well, otherwise just the provided object will.
+		/// </param>
+		public SerializedSceneObject(SceneObject sceneObject, bool hierarchy = false)
+		{
+			Internal_SerializedSceneObject(this, sceneObject, hierarchy);
+		}
+
+		/// <summary>
+		/// Restores the scene object to the state as it was when this object was created. If the scene object was deleted since 
+		/// it will be resurrected.
+		/// </summary>
+		public void Restore()
+		{
+			Internal_restore(mCachedPtr);
+		}
+
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_SerializedSceneObject(SerializedSceneObject managedInstance, SceneObject sceneObject, bool hierarchy);
+		[MethodImpl(MethodImplOptions.InternalCall)]
+		private static extern void Internal_restore(IntPtr thisPtr);
+	}
+
+	/** @} */
+}

+ 3 - 0
Source/EditorManaged/Generated/info.xml

@@ -319,6 +319,9 @@
 		<field name="icon256" type="RRef&lt;Texture&gt;">
 		<field name="icon256" type="RRef&lt;Texture&gt;">
 		</field>
 		</field>
 	</struct>
 	</struct>
+	<class native="SerializedSceneObject" script="SerializedSceneObject">
+		<doc>Serializes the current state of a scene object and allows that state to be restored. The advantage of using this  class versus normal serialization is that the deserialization happens into the original scene object, instead of creating a new scene object.</doc>
+	</class>
 	<enum native="ProjectLibraryIcon" script="ProjectLibraryIcon">
 	<enum native="ProjectLibraryIcon" script="ProjectLibraryIcon">
 		<doc>Types of valid icons used when viewing the project library.</doc>
 		<doc>Types of valid icons used when viewing the project library.</doc>
 		<enumentry native="ShaderInclude" script="ShaderInclude">
 		<enumentry native="ShaderInclude" script="ShaderInclude">

+ 0 - 50
Source/EditorManaged/Utility/SerializedSceneObject.cs

@@ -1,50 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-using System;
-using System.Runtime.CompilerServices;
-using bs;
-
-namespace bs.Editor
-{
-    /** @addtogroup Utility-Editor
-     *  @{
-     */
-
-    /// <summary>
-    /// Records a state of a scene object, it's components and optionally its child hierarchy. Stored state can
-    /// be applied to a scene object in order to restore the originally recorded state.
-    /// </summary>
-    public class SerializedSceneObject : ScriptObject
-    {
-        /// <summary>
-        /// Records the current state of the provided scene object.
-        /// </summary>
-        /// <param name="so">Scene object to record the state for.</param>
-        /// <param name="hierarchy">If true, state will be recorded for the scene object and all of its children. Otherwise
-        ///                         the state will only be recorded for the provided scene object.</param>
-        public SerializedSceneObject(SceneObject so, bool hierarchy)
-        {
-            IntPtr soPtr = IntPtr.Zero;
-            if (so != null)
-                soPtr = so.GetCachedPtr();
-
-            Internal_CreateInstance(this, soPtr, hierarchy);
-        }
-
-        /// <summary>
-        /// Restores the referenced scene object to its original state.
-        /// </summary>
-        public void Restore()
-        {
-            Internal_Restore(mCachedPtr);
-        }
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_CreateInstance(SerializedSceneObject instance, IntPtr so, bool hierarchy);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Restore(IntPtr thisPtr);
-    }
-
-    /** @} */
-}

+ 0 - 2
Source/EditorScript/CMakeSources.cmake

@@ -68,7 +68,6 @@ set(BS_EDITORSCRIPT_SRC_WRAPPERS
 	"Wrappers/BsScriptUnitTests.cpp"
 	"Wrappers/BsScriptUnitTests.cpp"
 	"Wrappers/BsScriptSerializedObject.cpp"
 	"Wrappers/BsScriptSerializedObject.cpp"
 	"Wrappers/BsScriptSerializedDiff.cpp"
 	"Wrappers/BsScriptSerializedDiff.cpp"
-	"Wrappers/BsScriptSerializedSceneObject.cpp"
 )
 )
 
 
 set(BS_EDITORSCRIPT_SRC_NOFILTER
 set(BS_EDITORSCRIPT_SRC_NOFILTER
@@ -123,7 +122,6 @@ set(BS_EDITORSCRIPT_INC_WRAPPERS
 	"Wrappers/BsScriptHandleDrawing.h"
 	"Wrappers/BsScriptHandleDrawing.h"
 	"Wrappers/BsScriptSerializedObject.h"
 	"Wrappers/BsScriptSerializedObject.h"
 	"Wrappers/BsScriptSerializedDiff.h"	
 	"Wrappers/BsScriptSerializedDiff.h"	
-	"Wrappers/BsScriptSerializedSceneObject.h"
 )
 )
 
 
 set(BS_EDITORSCRIPT_INC_WRAPPERS_GUI
 set(BS_EDITORSCRIPT_INC_WRAPPERS_GUI

+ 51 - 0
Source/EditorScript/Generated/BsScriptSerializedSceneObject.generated.cpp

@@ -0,0 +1,51 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//************** Copyright (c) 2016-2019 Marko Pintera ([email protected]). All rights reserved. *******************//
+#include "BsScriptSerializedSceneObject.generated.h"
+#include "BsMonoMethod.h"
+#include "BsMonoClass.h"
+#include "BsMonoUtil.h"
+#include "../../EditorCore/Scene/BsSerializedSceneObject.h"
+#include "BsScriptGameObjectManager.h"
+#include "Wrappers/BsScriptSceneObject.h"
+
+namespace bs
+{
+	ScriptSerializedSceneObject::ScriptSerializedSceneObject(MonoObject* managedInstance, const SPtr<SerializedSceneObject>& value)
+		:ScriptObject(managedInstance), mInternal(value)
+	{
+	}
+
+	void ScriptSerializedSceneObject::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_SerializedSceneObject", (void*)&ScriptSerializedSceneObject::Internal_SerializedSceneObject);
+		metaData.scriptClass->addInternalCall("Internal_restore", (void*)&ScriptSerializedSceneObject::Internal_restore);
+
+	}
+
+	MonoObject* ScriptSerializedSceneObject::create(const SPtr<SerializedSceneObject>& value)
+	{
+		if(value == nullptr) return nullptr; 
+
+		bool dummy = false;
+		void* ctorParams[1] = { &dummy };
+
+		MonoObject* managedInstance = metaData.scriptClass->createInstance("bool", ctorParams);
+		new (bs_alloc<ScriptSerializedSceneObject>()) ScriptSerializedSceneObject(managedInstance, value);
+		return managedInstance;
+	}
+	void ScriptSerializedSceneObject::Internal_SerializedSceneObject(MonoObject* managedInstance, MonoObject* sceneObject, bool hierarchy)
+	{
+		GameObjectHandle<SceneObject> tmpsceneObject;
+		ScriptSceneObject* scriptsceneObject;
+		scriptsceneObject = ScriptSceneObject::toNative(sceneObject);
+		if(scriptsceneObject != nullptr)
+			tmpsceneObject = scriptsceneObject->getHandle();
+		SPtr<SerializedSceneObject> instance = bs_shared_ptr_new<SerializedSceneObject>(tmpsceneObject, hierarchy);
+		new (bs_alloc<ScriptSerializedSceneObject>())ScriptSerializedSceneObject(managedInstance, instance);
+	}
+
+	void ScriptSerializedSceneObject::Internal_restore(ScriptSerializedSceneObject* thisPtr)
+	{
+		thisPtr->getInternal()->restore();
+	}
+}

+ 28 - 0
Source/EditorScript/Generated/BsScriptSerializedSceneObject.generated.h

@@ -0,0 +1,28 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//************** Copyright (c) 2016-2019 Marko Pintera ([email protected]). All rights reserved. *******************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace bs
+{
+	class SerializedSceneObject;
+
+	class BS_SCR_BED_EXPORT ScriptSerializedSceneObject : public ScriptObject<ScriptSerializedSceneObject>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, EDITOR_NS, "SerializedSceneObject")
+
+		ScriptSerializedSceneObject(MonoObject* managedInstance, const SPtr<SerializedSceneObject>& value);
+
+		SPtr<SerializedSceneObject> getInternal() const { return mInternal; }
+		static MonoObject* create(const SPtr<SerializedSceneObject>& value);
+
+	private:
+		SPtr<SerializedSceneObject> mInternal;
+
+		static void Internal_SerializedSceneObject(MonoObject* managedInstance, MonoObject* sceneObject, bool hierarchy);
+		static void Internal_restore(ScriptSerializedSceneObject* thisPtr);
+	};
+}

+ 0 - 120
Source/EditorScript/Wrappers/BsScriptSerializedSceneObject.cpp

@@ -1,120 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "Wrappers/BsScriptSerializedSceneObject.h"
-#include "BsScriptMeta.h"
-#include "BsMonoClass.h"
-#include "Wrappers/BsScriptSceneObject.h"
-#include "Scene/BsSceneObject.h"
-#include "Serialization/BsMemorySerializer.h"
-#include "Utility/BsUtility.h"
-
-namespace bs
-{
-	ScriptSerializedSceneObject::ScriptSerializedSceneObject(MonoObject* instance, const HSceneObject& so, bool recordHierarchy)
-		: ScriptObject(instance), mSO(so), mRecordHierarchy(recordHierarchy), mSerializedObject(nullptr), mSerializedObjectSize(0)
-	{
-		if (mSO.isDestroyed())
-			return;
-
-		UINT32 numChildren = mSO->getNumChildren();
-		HSceneObject* children = nullptr;
-
-		if (!mRecordHierarchy)
-		{
-			children = bs_stack_new<HSceneObject>(numChildren);
-			for (UINT32 i = 0; i < numChildren; i++)
-			{
-				HSceneObject child = mSO->getChild(i);
-				children[i] = child;
-
-				child->setParent(HSceneObject());
-			}
-		}
-
-		bool isInstantiated = !mSO->hasFlag(SOF_DontInstantiate);
-		mSO->_setFlags(SOF_DontInstantiate);
-
-		MemorySerializer serializer;
-		mSerializedObject = serializer.encode(mSO.get(), mSerializedObjectSize);
-
-		if (isInstantiated)
-			mSO->_unsetFlags(SOF_DontInstantiate);
-
-		mSceneObjectProxy = EditorUtility::createProxy(mSO);
-
-		if (!mRecordHierarchy)
-		{
-			for (UINT32 i = 0; i < numChildren; i++)
-				children[i]->setParent(mSO->getHandle());
-
-			bs_stack_delete(children, numChildren);
-		}
-	}
-
-	ScriptSerializedSceneObject::~ScriptSerializedSceneObject()
-	{
-		if (mSerializedObject != nullptr)
-			bs_free(mSerializedObject);
-	}
-
-	void ScriptSerializedSceneObject::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_CreateInstance", (void*)&ScriptSerializedSceneObject::internal_CreateInstance);
-		metaData.scriptClass->addInternalCall("Internal_Restore", (void*)&ScriptSerializedSceneObject::internal_Restore);
-	}
-
-	void ScriptSerializedSceneObject::internal_CreateInstance(MonoObject* instance, ScriptSceneObject* so, bool hierarchy)
-	{
-		HSceneObject sceneObj;
-		if (so != nullptr)
-			sceneObj = so->getHandle();
-
-		new (bs_alloc<ScriptSerializedSceneObject>()) ScriptSerializedSceneObject(instance, sceneObj, hierarchy);
-	}
-
-	void ScriptSerializedSceneObject::internal_Restore(ScriptSerializedSceneObject* thisPtr)
-	{
-		HSceneObject sceneObj = thisPtr->mSO;
-
-		if (sceneObj.isDestroyed())
-			return;
-
-		HSceneObject parent = sceneObj->getParent();
-
-		UINT32 numChildren = sceneObj->getNumChildren();
-		HSceneObject* children = nullptr;
-		if (!thisPtr->mRecordHierarchy)
-		{
-			children = bs_stack_new<HSceneObject>(numChildren);
-			for (UINT32 i = 0; i < numChildren; i++)
-			{
-				HSceneObject child = sceneObj->getChild(i);
-				children[i] = child;
-
-				child->setParent(HSceneObject());
-			}
-		}
-
-		sceneObj->destroy(true);
-
-		CoreSerializationContext serzContext;
-		serzContext.goState = bs_shared_ptr_new<GameObjectDeserializationState>(GODM_RestoreExternal | GODM_UseNewIds);
-
-		MemorySerializer serializer;
-		SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(
-			serializer.decode(thisPtr->mSerializedObject, thisPtr->mSerializedObjectSize, &serzContext));
-
-		EditorUtility::restoreIds(restored->getHandle(), thisPtr->mSceneObjectProxy);
-		restored->setParent(parent);
-
-		if (!thisPtr->mRecordHierarchy)
-		{
-			for (UINT32 i = 0; i < numChildren; i++)
-				children[i]->setParent(restored->getHandle());
-
-			bs_stack_delete(children, numChildren);
-		}
-
-		restored->_instantiate();
-	}
-}

+ 0 - 41
Source/EditorScript/Wrappers/BsScriptSerializedSceneObject.h

@@ -1,41 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsScriptEditorPrerequisites.h"
-#include "BsScriptObject.h"
-#include "Utility/BsEditorUtility.h"
-
-namespace bs
-{
-	/** @addtogroup ScriptInteropEditor
-	 *  @{
-	 */
-
-	/**	Interop class between C++ & CLR for SerializedSceneObject. */
-	class BS_SCR_BED_EXPORT ScriptSerializedSceneObject : public ScriptObject <ScriptSerializedSceneObject>
-	{
-	public:
-		SCRIPT_OBJ(EDITOR_ASSEMBLY, EDITOR_NS, "SerializedSceneObject")
-
-	private:
-		ScriptSerializedSceneObject(MonoObject* instance, const HSceneObject& so, bool recordHierarchy);
-		~ScriptSerializedSceneObject();
-
-		HSceneObject mSO;
-
-		EditorUtility::SceneObjProxy mSceneObjectProxy;
-		bool mRecordHierarchy;
-
-		UINT8* mSerializedObject;
-		UINT32 mSerializedObjectSize;
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_CreateInstance(MonoObject* instance, ScriptSceneObject* so, bool hierarchy);
-		static void internal_Restore(ScriptSerializedSceneObject* thisPtr);
-	};
-
-	/** @} */
-}