Pārlūkot izejas kodu

Do not redundantly recurse during updateFromPrefab with larger prefab instance hierarchies
Ensure that external prefab game object references are broken on prefab deserialization (not tested if this works)

BearishSun 10 gadi atpakaļ
vecāks
revīzija
cff23180f3

+ 1 - 1
BansheeCore/Include/BsGameObjectManager.h

@@ -110,7 +110,7 @@ namespace BansheeEngine
 		//  - 1. Resolves all GameObjectHandles on deserialization
 		//  - 1. Resolves all GameObjectHandles on deserialization
 		//    - We can't just resolve them as we go because during deserialization not all objects
 		//    - We can't just resolve them as we go because during deserialization not all objects
 		//      have necessarily been created.
 		//      have necessarily been created.
-		//  - 2. Maps serialized IDs to actual in-engine ids. 
+		//  - 2. Maps serialized IDs to actual in-engine IDs. 
 
 
 		/**
 		/**
 		 * @brief	Needs to be called whenever GameObject deserialization starts. Must be followed
 		 * @brief	Needs to be called whenever GameObject deserialization starts. Must be followed

+ 9 - 6
BansheeCore/Include/BsPrefab.h

@@ -29,13 +29,9 @@ namespace BansheeEngine
 		 *			scene object hierarchy. The returned hierarchy will be parented
 		 *			scene object hierarchy. The returned hierarchy will be parented
 		 *			to world root by default.
 		 *			to world root by default.
 		 *			
 		 *			
-		 * @param	onlyClone	If true the internal prefab hierarchy will be cloned and returned, but not actually 
-		 * 						instantiated. Caller must ensure to call ::instantiate on the returned scene object. 
-		 * 						If false the returned scene object will be instantiated before returning.
-		 * 						
-		 * @returns	Clone of the prefab's scene object hierarchy.
+		 * @returns	Instantiated clone of the prefab's scene object hierarchy.
 		 */
 		 */
-		HSceneObject instantiate(bool onlyClone = false);
+		HSceneObject instantiate();
 
 
 		/**
 		/**
 		 * @brief	Replaces the contents of this prefab with new contents
 		 * @brief	Replaces the contents of this prefab with new contents
@@ -52,6 +48,13 @@ namespace BansheeEngine
 		 */
 		 */
 		HSceneObject _getRoot() const { return mRoot; }
 		HSceneObject _getRoot() const { return mRoot; }
 
 
+		/**
+		 * @brief	Creates the clone of the prefab's current hierarchy but doesn't instantiate it.
+		 *			
+		 * @returns	Clone of the prefab's scene object hierarchy.
+		 */
+		HSceneObject _clone();
+
 		/**
 		/**
 		 * @brief	Returns a hash value that can be used for determining if a prefab changed
 		 * @brief	Returns a hash value that can be used for determining if a prefab changed
 		 *			by comparing it to a previously saved hash.
 		 *			by comparing it to a previously saved hash.

+ 8 - 0
BansheeCore/Include/BsPrefabRTTI.h

@@ -27,6 +27,14 @@ namespace BansheeEngine
 			addPlainField("mNextLinkId", 2, &PrefabRTTI::getNextLinkId, &PrefabRTTI::setNextLinkId);
 			addPlainField("mNextLinkId", 2, &PrefabRTTI::getNextLinkId, &PrefabRTTI::setNextLinkId);
 		}
 		}
 
 
+		virtual void onDeserializationStarted(IReflectable* ptr) override
+		{
+			// Make sure external IDs are broken because we do some ID matching when dealing with prefabs and keeping
+			// the invalid external references could cause it to match invalid objects in case they end up having the
+			// same ID.
+			GameObjectManager::instance().setDeserializationMode(GODM_UseNewIds | GODM_BreakExternal);
+		}
+
 		virtual const String& getRTTIName() override
 		virtual const String& getRTTIName() override
 		{
 		{
 			static String name = "Prefab";
 			static String name = "Prefab";

+ 12 - 7
BansheeCore/Source/BsPrefab.cpp

@@ -108,7 +108,7 @@ namespace BansheeEngine
 		mHash++;
 		mHash++;
 	}
 	}
 
 
-	HSceneObject Prefab::instantiate(bool onlyClone)
+	HSceneObject Prefab::instantiate()
 	{
 	{
 		if (mRoot == nullptr)
 		if (mRoot == nullptr)
 			return HSceneObject();
 			return HSceneObject();
@@ -136,16 +136,21 @@ namespace BansheeEngine
 		}
 		}
 #endif
 #endif
 
 
-		mRoot->mPrefabHash = mHash;
-
-		HSceneObject clone = mRoot->clone();
-
-		if (!onlyClone)
-			clone->instantiate();
+		HSceneObject clone = _clone();
+		clone->instantiate();
 		
 		
 		return clone;
 		return clone;
 	}
 	}
 
 
+	HSceneObject Prefab::_clone()
+	{
+		if (mRoot == nullptr)
+			return HSceneObject();
+
+		mRoot->mPrefabHash = mHash;
+		return mRoot->clone();
+	}
+
 	RTTITypeBase* Prefab::getRTTIStatic()
 	RTTITypeBase* Prefab::getRTTIStatic()
 	{
 	{
 		return PrefabRTTI::instance();
 		return PrefabRTTI::instance();

+ 1 - 1
BansheeCore/Source/BsPrefabDiff.cpp

@@ -382,7 +382,7 @@ namespace BansheeEngine
 			String uuid;
 			String uuid;
 		};
 		};
 
 
-		// When renaming it is important to rename the instance and not the prefab, since the diff will otherwise
+		// When renaming it is important to rename the prefab and not the instance, since the diff will otherwise
 		// contain prefab's IDs, but will be used for the instance.
 		// contain prefab's IDs, but will be used for the instance.
 
 
 		Stack<StackEntry> todo;
 		Stack<StackEntry> todo;

+ 1 - 1
BansheeCore/Source/BsPrefabUtility.cpp

@@ -103,7 +103,7 @@ namespace BansheeEngine
 				PrefabDiffPtr prefabDiff = current->mPrefabDiff;
 				PrefabDiffPtr prefabDiff = current->mPrefabDiff;
 
 
 				current->destroy(true);
 				current->destroy(true);
-				HSceneObject newInstance = prefabLink->instantiate(true);
+				HSceneObject newInstance = prefabLink->_clone();
 
 
 				// When restoring instance IDs it is important to make all the new handles point to the old GameObjectInstanceData.
 				// When restoring instance IDs it is important to make all the new handles point to the old GameObjectInstanceData.
 				// This is because old handles will have different GameObjectHandleData and we have no easy way of accessing it to
 				// This is because old handles will have different GameObjectHandleData and we have no easy way of accessing it to