Browse Source

Scene object state can now be recorded using SerializedSceneObject and restored to original state on request

BearishSun 9 years ago
parent
commit
61b712dc2c

+ 0 - 2
Source/BansheeEditor/CMakeSources.cmake

@@ -108,7 +108,6 @@ set(BS_BANSHEEEDITOR_INC_UNDOREDO
 	"Include/BsCmdReparentSO.h"
 	"Include/BsCmdInputFieldValueChange.h"
 	"Include/BsCmdRecordSO.h"
-	"Include/BsCmdUtility.h"
 	"Include/BsCmdDeleteSO.h"
 	"Include/BsCmdCreateSO.h"
 	"Include/BsCmdCloneSO.h"
@@ -196,7 +195,6 @@ set(BS_BANSHEEEDITOR_SRC_UNDOREDO
 	"Source/BsEditorCommand.cpp"
 	"Source/BsCmdReparentSO.cpp"
 	"Source/BsCmdRecordSO.cpp"
-	"Source/BsCmdUtility.cpp"
 	"Source/BsCmdDeleteSO.cpp"
 	"Source/BsCmdCreateSO.cpp"
 	"Source/BsCmdCloneSO.cpp"

+ 0 - 1
Source/BansheeEditor/Include/BsCmdCloneSO.h

@@ -5,7 +5,6 @@
 #include "BsEditorPrerequisites.h"
 #include "BsEditorCommand.h"
 #include "BsUndoRedo.h"
-#include "BsCmdUtility.h"
 
 namespace BansheeEngine
 {

+ 0 - 1
Source/BansheeEditor/Include/BsCmdCreateSO.h

@@ -5,7 +5,6 @@
 #include "BsEditorPrerequisites.h"
 #include "BsEditorCommand.h"
 #include "BsUndoRedo.h"
-#include "BsCmdUtility.h"
 
 namespace BansheeEngine
 {

+ 2 - 2
Source/BansheeEditor/Include/BsCmdDeleteSO.h

@@ -5,7 +5,7 @@
 #include "BsEditorPrerequisites.h"
 #include "BsEditorCommand.h"
 #include "BsUndoRedo.h"
-#include "BsCmdUtility.h"
+#include "BsEditorUtility.h"
 
 namespace BansheeEngine
 {
@@ -49,7 +49,7 @@ namespace BansheeEngine
 		void clear();
 
 		HSceneObject mSceneObject;
-		CmdUtility::SceneObjProxy mSceneObjectProxy;
+		EditorUtility::SceneObjProxy mSceneObjectProxy;
 
 		UINT8* mSerializedObject;
 		UINT32 mSerializedObjectSize;

+ 0 - 1
Source/BansheeEditor/Include/BsCmdInstantiateSO.h

@@ -5,7 +5,6 @@
 #include "BsEditorPrerequisites.h"
 #include "BsEditorCommand.h"
 #include "BsUndoRedo.h"
-#include "BsCmdUtility.h"
 
 namespace BansheeEngine
 {

+ 2 - 2
Source/BansheeEditor/Include/BsCmdRecordSO.h

@@ -5,7 +5,7 @@
 #include "BsEditorPrerequisites.h"
 #include "BsEditorCommand.h"
 #include "BsUndoRedo.h"
-#include "BsCmdUtility.h"
+#include "BsEditorUtility.h"
 
 namespace BansheeEngine
 {
@@ -54,7 +54,7 @@ namespace BansheeEngine
 		void clear();
 
 		HSceneObject mSceneObject;
-		CmdUtility::SceneObjProxy mSceneObjectProxy;
+		EditorUtility::SceneObjProxy mSceneObjectProxy;
 		bool mRecordHierarchy;
 
 		UINT8* mSerializedObject;

+ 0 - 51
Source/BansheeEditor/Include/BsCmdUtility.h

@@ -1,51 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#pragma once
-
-#include "BsEditorPrerequisites.h"
-
-namespace BansheeEngine
-{
-	/** @addtogroup UndoRedo
-	 *  @{
-	 */
-
-	/** Contains various utility methods and structures used by EditorCommand%s. */
-	class CmdUtility
-	{
-	public:
-		/**
-		 * Contains stored information about stored scene object instance data, including all of its children and
-		 * components.
-		 *
-		 * @note	
-		 * When object is serialized it will receive new instance data (as if it was a new object). But we want to restore
-		 * the original object completely (including any references	other objects might have to it) so we need store the
-		 * instance data.
-		 */
-		struct SceneObjProxy
-		{
-			GameObjectInstanceDataPtr instanceData;
-
-			Vector<GameObjectInstanceDataPtr> componentInstanceData;
-			Vector<SceneObjProxy> children;
-		};
-
-		/**
-		 * Parses the scene object hierarchy and components and generates a hierarchy of instance data required to restore
-		 * the object identities.
-		 */
-		static SceneObjProxy createProxy(const HSceneObject& sceneObject);
-
-		/**
-		 * Restores original object instance data from the provided scene object proxy that was previously generated using
-		 * createProxy().
-		 *
-		 * @param[in]	restored	New instance of the object.
-		 * @param[in]	proxy		Proxy data containing the original object instance data we want to restore.
-		 */
-		static void restoreIds(const HSceneObject& restored, SceneObjProxy& proxy);
-	};
-
-	/** @} */
-}

+ 32 - 0
Source/BansheeEditor/Include/BsEditorUtility.h

@@ -15,6 +15,23 @@ namespace BansheeEngine
 	class BS_ED_EXPORT EditorUtility
 	{
 	public:
+		/**
+		 * Contains stored information about stored scene object instance data, including all of its children and
+		 * components.
+		 *
+		 * @note	
+		 * When object is serialized it will receive new instance data (as if it was a new object). But we want to restore
+		 * the original object completely (including any references	other objects might have to it) so we need store the
+		 * instance data.
+		 */
+		struct SceneObjProxy
+		{
+			GameObjectInstanceDataPtr instanceData;
+
+			Vector<GameObjectInstanceDataPtr> componentInstanceData;
+			Vector<SceneObjProxy> children;
+		};
+
 		/**
 		 * Calculates world space bounds of the specified scene object. This will consider components with bounds like
 		 * Renderable.
@@ -30,6 +47,21 @@ namespace BansheeEngine
 		/** Calculates world space center of the specified scene objects. */
 		static Vector3 calculateCenter(const Vector<HSceneObject>& objects);
 
+		/**
+		 * Parses the scene object hierarchy and components and generates a hierarchy of instance data required to restore
+		 * the object identities.
+		 */
+		static SceneObjProxy createProxy(const HSceneObject& sceneObject);
+
+		/**
+		 * Restores original object instance data from the provided scene object proxy that was previously generated using
+		 * createProxy().
+		 *
+		 * @param[in]	restored	New instance of the object.
+		 * @param[in]	proxy		Proxy data containing the original object instance data we want to restore.
+		 */
+		static void restoreIds(const HSceneObject& restored, SceneObjProxy& proxy);
+
 	private:
 		/**
 		 * Retrieves all components containing meshes on the specified object and outputs their bounds.

+ 2 - 2
Source/BansheeEditor/Source/BsCmdDeleteSO.cpp

@@ -70,7 +70,7 @@ namespace BansheeEngine
 		MemorySerializer serializer;
 		SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(serializer.decode(mSerializedObject, mSerializedObjectSize));
 
-		CmdUtility::restoreIds(restored->getHandle(), mSceneObjectProxy);
+		EditorUtility::restoreIds(restored->getHandle(), mSceneObjectProxy);
 		restored->setParent(parent);
 	}
 
@@ -83,6 +83,6 @@ namespace BansheeEngine
 		if (parent != nullptr)
 			mSerializedObjectParentId = parent->getInstanceId();
 
-		mSceneObjectProxy = CmdUtility::createProxy(mSceneObject);
+		mSceneObjectProxy = EditorUtility::createProxy(mSceneObject);
 	}
 }

+ 2 - 2
Source/BansheeEditor/Source/BsCmdRecordSO.cpp

@@ -77,7 +77,7 @@ namespace BansheeEngine
 		MemorySerializer serializer;
 		SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(serializer.decode(mSerializedObject, mSerializedObjectSize));
 
-		CmdUtility::restoreIds(restored->getHandle(), mSceneObjectProxy);
+		EditorUtility::restoreIds(restored->getHandle(), mSceneObjectProxy);
 		restored->setParent(parent);
 
 		if (!mRecordHierarchy)
@@ -109,7 +109,7 @@ namespace BansheeEngine
 		MemorySerializer serializer;
 		mSerializedObject = serializer.encode(mSceneObject.get(), mSerializedObjectSize);
 
-		mSceneObjectProxy = CmdUtility::createProxy(mSceneObject);
+		mSceneObjectProxy = EditorUtility::createProxy(mSceneObject);
 
 		if (!mRecordHierarchy)
 		{

+ 0 - 100
Source/BansheeEditor/Source/BsCmdUtility.cpp

@@ -1,100 +0,0 @@
-//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
-//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
-#include "BsCmdUtility.h"
-#include "BsSceneObject.h"
-
-namespace BansheeEngine
-{
-	CmdUtility::SceneObjProxy CmdUtility::createProxy(const HSceneObject& sceneObject)
-	{
-		struct TempData
-		{
-			TempData(SceneObjProxy& proxy, const HSceneObject& so)
-				:proxy(proxy), obj(so)
-			{ }
-
-			SceneObjProxy& proxy;
-			HSceneObject obj;
-		};
-
-		SceneObjProxy rootProxy;
-
-		Stack<TempData> todo;
-		todo.push(TempData(rootProxy, sceneObject));
-
-		while (!todo.empty())
-		{
-			TempData data = todo.top();
-			todo.pop();
-
-			data.proxy.instanceData = data.obj->_getInstanceData();
-
-			const Vector<HComponent>& components = data.obj->getComponents();
-			for (auto& component : components)
-				data.proxy.componentInstanceData.push_back(component->_getInstanceData());
-
-			UINT32 numChildren = data.obj->getNumChildren();
-			data.proxy.children.resize(numChildren);
-			for (UINT32 i = 0; i < numChildren; i++)
-			{
-				todo.push(TempData(data.proxy.children[i], data.obj->getChild(i)));
-			}
-		}
-
-		return rootProxy;
-	}
-
-
-	void CmdUtility::restoreIds(const HSceneObject& restored, SceneObjProxy& proxy)
-	{
-		// Note: This method relies that all restored GameObject handles pointing to the
-		// same object also have the same shared handle data (Since I only update instance
-		// data on a single handle I know exists, and expect all others will be updated
-		// by that as well).
-
-		struct TempData
-		{
-			TempData(SceneObjProxy& proxy, const HSceneObject& restoredObj)
-			:proxy(proxy), restoredObj(restoredObj)
-			{ }
-
-			SceneObjProxy& proxy;
-			HSceneObject restoredObj;
-		};
-
-		Stack<TempData> todo;
-		todo.push(TempData(proxy, restored));
-
-		while (!todo.empty())
-		{
-			TempData data = todo.top();
-			todo.pop();
-
-			data.restoredObj->_setInstanceData(data.proxy.instanceData);
-
-			// Find components that are still active and swap the old ones with restored ones,
-			// keep any other as is.
-			const Vector<HComponent>& restoredComponents = data.restoredObj->getComponents();
-
-			UINT32 idx = 0;
-			for (auto& restoredComponent : restoredComponents)
-			{
-				restoredComponent->_setInstanceData(data.proxy.componentInstanceData[idx]);
-
-				SPtr<GameObject> restoredPtr = std::static_pointer_cast<GameObject>(restoredComponent.getInternalPtr());
-				HComponent restoredComponentCopy = restoredComponent; // To remove const
-				restoredComponentCopy._setHandleData(restoredPtr);
-
-				idx++;
-			}
-			
-			// Find children that are still active and swap the old ones with restored ones,
-			// keep any other as is
-			UINT32 restoredNumChildren = data.restoredObj->getNumChildren();
-			for (UINT32 i = 0; i < restoredNumChildren; i++)
-			{
-				todo.push(TempData(data.proxy.children[i], data.restoredObj->getChild(i)));
-			}
-		}
-	}
-}

+ 92 - 1
Source/BansheeEditor/Source/BsEditorUtility.cpp

@@ -92,7 +92,6 @@ namespace BansheeEngine
 		return Vector3::ZERO;
 	}
 
-
 	bool EditorUtility::calculateMeshBounds(const HSceneObject& object, AABox& bounds)
 	{
 		bounds = AABox(Vector3::ZERO, Vector3::ZERO);
@@ -123,4 +122,96 @@ namespace BansheeEngine
 
 		return foundOne;
 	}
+
+	EditorUtility::SceneObjProxy EditorUtility::createProxy(const HSceneObject& sceneObject)
+	{
+		struct TempData
+		{
+			TempData(SceneObjProxy& proxy, const HSceneObject& so)
+				:proxy(proxy), obj(so)
+			{ }
+
+			SceneObjProxy& proxy;
+			HSceneObject obj;
+		};
+
+		SceneObjProxy rootProxy;
+
+		Stack<TempData> todo;
+		todo.push(TempData(rootProxy, sceneObject));
+
+		while (!todo.empty())
+		{
+			TempData data = todo.top();
+			todo.pop();
+
+			data.proxy.instanceData = data.obj->_getInstanceData();
+
+			const Vector<HComponent>& components = data.obj->getComponents();
+			for (auto& component : components)
+				data.proxy.componentInstanceData.push_back(component->_getInstanceData());
+
+			UINT32 numChildren = data.obj->getNumChildren();
+			data.proxy.children.resize(numChildren);
+			for (UINT32 i = 0; i < numChildren; i++)
+			{
+				todo.push(TempData(data.proxy.children[i], data.obj->getChild(i)));
+			}
+		}
+
+		return rootProxy;
+	}
+
+	void EditorUtility::restoreIds(const HSceneObject& restored, SceneObjProxy& proxy)
+	{
+		// Note: This method relies that all restored GameObject handles pointing to the
+		// same object also have the same shared handle data (Since I only update instance
+		// data on a single handle I know exists, and expect all others will be updated
+		// by that as well).
+
+		struct TempData
+		{
+			TempData(SceneObjProxy& proxy, const HSceneObject& restoredObj)
+				:proxy(proxy), restoredObj(restoredObj)
+			{ }
+
+			SceneObjProxy& proxy;
+			HSceneObject restoredObj;
+		};
+
+		Stack<TempData> todo;
+		todo.push(TempData(proxy, restored));
+
+		while (!todo.empty())
+		{
+			TempData data = todo.top();
+			todo.pop();
+
+			data.restoredObj->_setInstanceData(data.proxy.instanceData);
+
+			// Find components that are still active and swap the old ones with restored ones,
+			// keep any other as is.
+			const Vector<HComponent>& restoredComponents = data.restoredObj->getComponents();
+
+			UINT32 idx = 0;
+			for (auto& restoredComponent : restoredComponents)
+			{
+				restoredComponent->_setInstanceData(data.proxy.componentInstanceData[idx]);
+
+				SPtr<GameObject> restoredPtr = std::static_pointer_cast<GameObject>(restoredComponent.getInternalPtr());
+				HComponent restoredComponentCopy = restoredComponent; // To remove const
+				restoredComponentCopy._setHandleData(restoredPtr);
+
+				idx++;
+			}
+
+			// Find children that are still active and swap the old ones with restored ones,
+			// keep any other as is
+			UINT32 restoredNumChildren = data.restoredObj->getNumChildren();
+			for (UINT32 i = 0; i < restoredNumChildren; i++)
+			{
+				todo.push(TempData(data.proxy.children[i], data.restoredObj->getChild(i)));
+			}
+		}
+	}
 }

+ 1 - 0
Source/MBansheeEditor/MBansheeEditor.csproj

@@ -48,6 +48,7 @@
     <Compile Include="Inspectors\BoneInspector.cs" />
     <Compile Include="Inspectors\PostProcessSettingsInspector.cs" />
     <Compile Include="Utility\EdAnimationCurve.cs" />
+    <Compile Include="Utility\SerializedSceneObject.cs" />
     <Compile Include="Utility\SerializedDiff.cs" />
     <Compile Include="Utility\SerializedObject.cs" />
     <Compile Include="Windows\AboutBox.cs" />

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

@@ -0,0 +1,50 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+using System;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    /** @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);
+    }
+
+    /** @} */
+}

+ 2 - 0
Source/SBansheeEditor/CMakeSources.cmake

@@ -70,6 +70,7 @@ set(BS_SBANSHEEEDITOR_SRC_WRAPPERS
 	"Source/BsScriptUnitTests.cpp"
 	"Source/BsScriptSerializedObject.cpp"
 	"Source/BsScriptSerializedDiff.cpp"
+	"Source/BsScriptSerializedSceneObject.cpp"
 )
 
 set(BS_SBANSHEEEDITOR_SRC_NOFILTER
@@ -124,6 +125,7 @@ set(BS_SBANSHEEEDITOR_INC_WRAPPERS
 	"Include/BsScriptHandleDrawing.h"
 	"Include/BsScriptSerializedObject.h"
 	"Include/BsScriptSerializedDiff.h"	
+	"Include/BsScriptSerializedSceneObject.h"
 )
 
 set(BS_SBANSHEEEDITOR_INC_WRAPPERS_GUI

+ 41 - 0
Source/SBansheeEditor/Include/BsScriptSerializedSceneObject.h

@@ -0,0 +1,41 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsEditorUtility.h"
+
+namespace BansheeEngine
+{
+	/** @addtogroup ScriptInteropEditor
+	 *  @{
+	 */
+
+	/**	Interop class between C++ & CLR for SerializedSceneObject. */
+	class BS_SCR_BED_EXPORT ScriptSerializedSceneObject : public ScriptObject <ScriptSerializedSceneObject>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "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);
+	};
+
+	/** @} */
+}

+ 110 - 0
Source/SBansheeEditor/Source/BsScriptSerializedSceneObject.cpp

@@ -0,0 +1,110 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsScriptSerializedSceneObject.h"
+#include "BsScriptMeta.h"
+#include "BsMonoClass.h"
+#include "BsScriptSceneObject.h"
+#include "BsSceneObject.h"
+#include "BsMemorySerializer.h"
+
+namespace BansheeEngine
+{
+	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());
+			}
+		}
+
+		MemorySerializer serializer;
+		mSerializedObject = serializer.encode(mSO.get(), mSerializedObjectSize);
+
+		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", &ScriptSerializedSceneObject::internal_CreateInstance);
+		metaData.scriptClass->addInternalCall("Internal_Restore", &ScriptSerializedSceneObject::internal_Restore);
+	}
+
+	void ScriptSerializedSceneObject::internal_CreateInstance(MonoObject* instance, ScriptSceneObject* so, bool hierarchy)
+	{
+		HSceneObject sceneObj;
+		if (so != nullptr)
+			sceneObj = so->getNativeSceneObject();
+
+		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);
+
+		GameObjectManager::instance().setDeserializationMode(GODM_RestoreExternal | GODM_UseNewIds);
+
+		MemorySerializer serializer;
+		SPtr<SceneObject> restored = std::static_pointer_cast<SceneObject>(
+			serializer.decode(thisPtr->mSerializedObject, thisPtr->mSerializedObjectSize));
+
+		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);
+		}
+	}
+}