Browse Source

More work on Play in editor

BearishSun 10 years ago
parent
commit
00d78189f3

+ 2 - 1
BansheeCore/Include/BsCoreSceneManager.h

@@ -30,7 +30,8 @@ namespace BansheeEngine
 		void clearScene(bool forceAll = false);
 
 		/**
-		 * @brief	Changes the root scene object.
+		 * @brief	Changes the root scene object. Any persistent objects will remain in the scene, now parented
+		 * 			to the new root.
 		 * 			
 		 * @note	Internal method.
 		 */

+ 11 - 6
BansheeCore/Include/BsSceneObject.h

@@ -93,6 +93,13 @@ namespace BansheeEngine
 		 */
 		bool hasFlag(UINT32 flag) const;
 
+		/**
+		 * @brief	Register the scene object with the scene and activate all of its components.
+		 * 		
+		 * @note	Internal method.
+		 */
+		void _instantiate();
+
 		/**
 		 * @brief	Clears the internally stored prefab diff. If this object is updated from prefab its instance specific
 		 * 			changes will be lost.
@@ -151,11 +158,6 @@ namespace BansheeEngine
 		 */
 		bool isInstantiated() const { return (mFlags & SOF_DontInstantiate) == 0; }
 
-		/**
-		 * @brief	Register the scene object with the scene and activate all of its components.
-		 */
-		void instantiate();
-
 	private:
 		HSceneObject mThisHandle;
 		String mPrefabLinkUUID;
@@ -472,8 +474,11 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Makes a deep copy of this object.
+		 * 			
+		 * @param	instantiate	If false, the cloned hierarchy will just be a memory copy, but will not be present in the
+		 * 						scene or otherwise active until ::instantiate() is called.
 		 */
-		HSceneObject clone();
+		HSceneObject clone(bool instantiate = true);
 
 	private:
 		HSceneObject mParent;

+ 1 - 1
BansheeCore/Include/BsSceneObjectRTTI.h

@@ -135,7 +135,7 @@ namespace BansheeEngine
 				GameObjectManager::instance().endDeserialization();
 
 				if ((so->mFlags & SOF_DontInstantiate) == 0)
-					so->instantiate();
+					so->_instantiate();
 			}
 
 			so->mRTTIData = nullptr;

+ 20 - 1
BansheeCore/Source/BsCoreSceneManager.cpp

@@ -38,8 +38,27 @@ namespace BansheeEngine
 
 	void CoreSceneManager::_setRootNode(const HSceneObject& root)
 	{
-		mRootNode = root; 
+		if (root == nullptr)
+			return;
+
+		HSceneObject oldRoot = mRootNode;
+
+		UINT32 numChildren = oldRoot->getNumChildren();
+		// Make sure to keep persistent objects
+
+		UINT32 curIdx = 0;
+		for (UINT32 i = 0; i < numChildren; i++)
+		{
+			HSceneObject child = oldRoot->getChild(curIdx);
+
+			if (child->hasFlag(SOF_Persistent))
+				child->setParent(root, false);
+		}
+
+		mRootNode = root;
 		mRootNode->_setParent(HSceneObject());
+
+		oldRoot->destroy();
 	}
 
 	void CoreSceneManager::_update()

+ 2 - 5
BansheeCore/Source/BsPrefab.cpp

@@ -74,10 +74,7 @@ namespace BansheeEngine
 		}
 
 		// Clone the hierarchy for internal storage
-		sceneObject->setFlags(SOF_DontInstantiate);
-		mRoot = sceneObject->clone();
-		sceneObject->unsetFlags(SOF_DontInstantiate);
-
+		mRoot = sceneObject->clone(false);
 		mRoot->mParent = nullptr;
 
 		// Remove objects with "dont save" flag
@@ -142,7 +139,7 @@ namespace BansheeEngine
 #endif
 
 		HSceneObject clone = _clone();
-		clone->instantiate();
+		clone->_instantiate();
 		
 		return clone;
 	}

+ 1 - 1
BansheeCore/Source/BsPrefabDiff.cpp

@@ -141,7 +141,7 @@ namespace BansheeEngine
 			BinarySerializer bs;
 			SPtr<SceneObject> sceneObject = std::static_pointer_cast<SceneObject>(bs._decodeIntermediate(addedChildData));
 			sceneObject->setParent(object);
-			sceneObject->instantiate();
+			sceneObject->_instantiate();
 		}
 
 		for (auto& componentDiff : diff->componentDiffs)

+ 8 - 2
BansheeCore/Source/BsSceneObject.cpp

@@ -176,7 +176,7 @@ namespace BansheeEngine
 			child->unsetFlags(flags);
 	}
 
-	void SceneObject::instantiate()
+	void SceneObject::_instantiate()
 	{
 		std::function<void(SceneObject*)> instantiateRecursive = [&](SceneObject* obj)
 		{
@@ -662,8 +662,11 @@ namespace BansheeEngine
 			return mActiveHierarchy;
 	}
 
-	HSceneObject SceneObject::clone()
+	HSceneObject SceneObject::clone(bool instantiate)
 	{
+		if (!instantiate)
+			setFlags(SOF_DontInstantiate);
+
 		UINT32 bufferSize = 0;
 
 		MemorySerializer serializer;
@@ -673,6 +676,9 @@ namespace BansheeEngine
 		std::shared_ptr<SceneObject> cloneObj = std::static_pointer_cast<SceneObject>(serializer.decode(buffer, bufferSize));
 		bs_free(buffer);
 
+		if (!instantiate)
+			unsetFlags(SOF_DontInstantiate);
+
 		return cloneObj->mThisHandle;
 	}
 

+ 13 - 1
Game/Game.vcxproj

@@ -142,6 +142,9 @@
       <AdditionalLibraryDirectories>..\lib\x86\$(Configuration);..\Dependencies\lib\x86\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>BansheeCore.lib;BansheeUtility.lib;BansheeEngine.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
+    <PostBuildEvent>
+      <Command>xcopy /Y /I "$(TargetDir)$(TargetName).exe" "$(SolutionDir)Data\Binaries\Win32\"</Command>
+    </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
@@ -188,6 +191,9 @@
       <AdditionalLibraryDirectories>..\lib\x86\$(Configuration);..\Dependencies\lib\x86\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>BansheeCore.lib;BansheeUtility.lib;BansheeEngine.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
+    <PostBuildEvent>
+      <Command>xcopy /Y /I "$(TargetDir)$(TargetName).exe" "$(SolutionDir)Data\Binaries\Win32\"</Command>
+    </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <ClCompile>
@@ -212,6 +218,9 @@
       <AdditionalLibraryDirectories>..\lib\x64\$(Configuration);..\Dependencies\lib\x64\Release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>BansheeCore.lib;BansheeUtility.lib;BansheeEngine.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
+    <PostBuildEvent>
+      <Command>xcopy /Y /I "$(TargetDir)$(TargetName).exe" "$(SolutionDir)Data\Binaries\Win64\"</Command>
+    </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugRelease|Win32'">
     <ClCompile>
@@ -236,6 +245,9 @@
       <AdditionalLibraryDirectories>..\lib\x86\$(Configuration);..\Dependencies\lib\x86\DebugRelease;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>BansheeCore.lib;BansheeUtility.lib;BansheeEngine.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
+    <PostBuildEvent>
+      <Command>xcopy /Y /I "$(TargetDir)$(TargetName).exe" "$(SolutionDir)Data\Binaries\Win32\"</Command>
+    </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugRelease|x64'">
     <ClCompile>
@@ -260,7 +272,7 @@
       <AdditionalDependencies>BansheeCore.lib;BansheeUtility.lib;BansheeEngine.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
     <PostBuildEvent>
-      <Command>copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)Data\Binaries\Win64\$(TargetName).dll"</Command>
+      <Command>xcopy /Y /I "$(TargetDir)$(TargetName).exe" "$(SolutionDir)Data\Binaries\Win64\"</Command>
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>

+ 2 - 2
MBansheeEditor/BuildWindow.cs

@@ -18,9 +18,9 @@ namespace BansheeEditor
         /// Opens the build window if its not open already.
         /// </summary>
         [MenuItem("Tools/Build", 9296)]
-        private static void OpenSettingsWindow()
+        private static void OpenBuildWindow()
         {
-            OpenWindow<SettingsWindow>();
+            OpenWindow<BuildWindow>();
         }
 
         /// <inheritdoc/>

+ 9 - 0
SBansheeEngine/Include/BsPlayInEditorManager.h

@@ -55,9 +55,18 @@ namespace BansheeEngine
 		void update();
 
 	private:
+		/**
+		 * @brief	Updates the play state of the game, making the game stop or start running. Unlike ::setState this
+		 * 			will trigger the state change right away.
+		 */
+		void setStateImmediate(PlayInEditorState state);
+
 		PlayInEditorState mState;
+		PlayInEditorState mNextState;
 		bool mFrameStepActive;
+		bool mScheduledStateChange;
 
 		float mPausableTime;
+		HSceneObject mSavedScene;
 	};
 }

+ 31 - 5
SBansheeEngine/Source/BsPlayInEditorManager.cpp

@@ -1,14 +1,25 @@
 #include "BsPlayInEditorManager.h"
 #include "BsScriptGameObjectManager.h"
 #include "BsTime.h"
+#include "BsSceneManager.h"
+#include "BsSceneObject.h"
 
 namespace BansheeEngine
 {
 	PlayInEditorManager::PlayInEditorManager()
-		:mState(PlayInEditorState::Stopped), mFrameStepActive(false)
+		:mState(PlayInEditorState::Stopped), mNextState(PlayInEditorState::Stopped), 
+		mFrameStepActive(false), mScheduledStateChange(false), mPausableTime(0.0f)
 	{ }
 
 	void PlayInEditorManager::setState(PlayInEditorState state)
+	{
+		// Delay state change to next frame as this method could be called in middle of object update, in which case
+		// part of the objects before this call would receive different state than other objects.
+		mScheduledStateChange = true;
+		mNextState = state;
+	}
+
+	void PlayInEditorManager::setStateImmediate(PlayInEditorState state)
 	{
 		if (mState == state)
 			return;
@@ -22,7 +33,10 @@ namespace BansheeEngine
 		{
 			mFrameStepActive = false;
 			mPausableTime = 0.0f;
-			// TODO - Load saved scene from prefab
+
+			mSavedScene->_instantiate();
+			gSceneManager()._setRootNode(mSavedScene);
+			mSavedScene = nullptr;
 		}
 			break;
 		case PlayInEditorState::Playing:
@@ -33,7 +47,8 @@ namespace BansheeEngine
 			}
 			else // Was stopped
 			{
-				// TODO - Save current scene in a prefab
+				mSavedScene = SceneManager::instance().getRootNode()->clone(false);
+				ScriptGameObjectManager::instance().sendComponentInitializeEvents();
 			}
 		}
 			break;
@@ -42,7 +57,8 @@ namespace BansheeEngine
 			mFrameStepActive = false;
 			if (oldState == PlayInEditorState::Stopped)
 			{
-				// TODO - Save current scene in a prefab
+				mSavedScene = SceneManager::instance().getRootNode()->clone(false);
+				ScriptGameObjectManager::instance().sendComponentInitializeEvents();
 			}
 		}
 			break;
@@ -69,6 +85,16 @@ namespace BansheeEngine
 		if (mState == PlayInEditorState::Playing)
 			mPausableTime += gTime().getFrameDelta();
 
-		// TODO - disable framestep once a frame has passed
+		if (mScheduledStateChange)
+		{
+			setStateImmediate(mNextState);
+			mScheduledStateChange = false;
+		}
+
+		if (mFrameStepActive)
+		{
+			setState(PlayInEditorState::Paused);
+			mFrameStepActive = false;
+		}
 	}
 }

+ 1 - 19
SBansheeEngine/Source/BsScriptScene.cpp

@@ -36,25 +36,7 @@ namespace BansheeEngine
 		if (prefab.isLoaded(false))
 		{
 			HSceneObject root = prefab->instantiate();
-			HSceneObject oldRoot = gSceneManager().getRootNode();
-
-			if (root != nullptr)
-			{
-				UINT32 numChildren = oldRoot->getNumChildren();
-				// Make sure to keep persistent objects
-				
-				UINT32 curIdx = 0;
-				for (UINT32 i = 0; i < numChildren; i++)
-				{
-					HSceneObject child = oldRoot->getChild(curIdx);
-
-					if (child->hasFlag(SOF_Persistent))
-						child->setParent(root, false);
-				}
-
-				gSceneManager()._setRootNode(root);
-				oldRoot->destroy();
-			}
+			gSceneManager()._setRootNode(root);
 		}
 
 		if (prefab != nullptr)