فهرست منبع

Fixed an issue with prefab diff deserialization
Changed how RTTI circular checks are handled so they work at runtime instead of compile time (checking just types isn't enough)

BearishSun 10 سال پیش
والد
کامیت
942e2897c4

+ 1 - 3
BansheeCore/Include/BsPrefabDiffRTTI.h

@@ -71,9 +71,7 @@ namespace BansheeEngine
 			BS_ADD_REFLPTR_FIELD_ARR(componentDiffs, 2);
 			BS_ADD_PLAIN_FIELD_ARR(removedComponents, 3);
 			BS_ADD_REFLPTR_FIELD_ARR(addedComponents, 4);
-
-			addReflectablePtrArrayField("childDiffs", 5, &MyType::getchildDiffs, &MyType::getSizechildDiffs,
-				&MyType::setchildDiffs, &MyType::setSizechildDiffs, RTTI_Flag_WeakRef);
+			BS_ADD_REFLPTR_FIELD_ARR(childDiffs, 5);
 
 			BS_ADD_PLAIN_FIELD_ARR(removedChildren, 6);
 			BS_ADD_REFLPTR_FIELD_ARR(addedChildren, 7);

+ 1 - 5
BansheeCore/Source/BsCoreApplication.cpp

@@ -47,11 +47,7 @@ namespace BansheeEngine
 	CoreApplication::CoreApplication(START_UP_DESC desc)
 		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false), 
 		mRendererPlugin(nullptr), mSimThreadId(BS_THREAD_CURRENT_ID), mStartUpDesc(desc)
-	{
-#if BS_DEBUG_MODE
-		IReflectable::_checkForCircularReferences();
-#endif
-	}
+	{ }
 
 	CoreApplication::~CoreApplication()
 	{

+ 2 - 1
BansheeUtility/Include/BsBinarySerializer.h

@@ -123,12 +123,13 @@ namespace BansheeEngine
 		struct ObjectToDecode
 		{
 			ObjectToDecode(const SPtr<IReflectable>& _object, const SPtr<SerializedObject>& serializedObject)
-				:object(_object), serializedObject(serializedObject), isDecoded(false)
+				:object(_object), serializedObject(serializedObject), isDecoded(false), decodeInProgress(false)
 			{ }
 
 			SPtr<IReflectable> object;
 			SPtr<SerializedObject> serializedObject;
 			bool isDecoded;
+			bool decodeInProgress; // Used for error reporting circular references
 		};
 
 		/** Encodes a single IReflectable object. */

+ 35 - 4
BansheeUtility/Source/BsBinarySerializer.cpp

@@ -141,7 +141,10 @@ namespace BansheeEngine
 		{
 			output = type->newRTTIObject();
 			auto iterNewObj = mObjectMap.insert(std::make_pair(serializedObject, ObjectToDecode(output, serializedObject)));
+
+			iterNewObj.first->second.decodeInProgress = true;
 			decodeInternal(output, serializedObject);
+			iterNewObj.first->second.decodeInProgress = false;
 			iterNewObj.first->second.isDecoded = true;
 		}
 
@@ -153,7 +156,9 @@ namespace BansheeEngine
 			if (objToDecode.isDecoded)
 				continue;
 
+			objToDecode.decodeInProgress = true;
 			decodeInternal(objToDecode.object, objToDecode.serializedObject);
+			objToDecode.decodeInProgress = false;
 			objToDecode.isDecoded = true;
 		}
 
@@ -932,8 +937,21 @@ namespace BansheeEngine
 								bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
 								if (needsDecoding)
 								{
-									decodeInternal(objToDecode.object, objToDecode.serializedObject);
-									objToDecode.isDecoded = true;
+									if (objToDecode.decodeInProgress)
+									{
+										LOGWRN("Detected a circular reference when decoding. Referenced object fields " \
+											"will be resolved in an undefined order (i.e. one of the objects will not " \
+											"be fully deserialized when assigned to its field). Use RTTI_Flag_WeakRef to " \
+											"get rid of this warning and tell the system which of the objects is allowed " \
+											"to be deserialized after it is assigned to its field.");
+									}
+									else
+									{
+										objToDecode.decodeInProgress = true;
+										decodeInternal(objToDecode.object, objToDecode.serializedObject);
+										objToDecode.decodeInProgress = false;
+										objToDecode.isDecoded = true;
+									}
 								}
 
 								curField->setArrayValue(object.get(), arrayElem.first, objToDecode.object);
@@ -1010,8 +1028,21 @@ namespace BansheeEngine
 							bool needsDecoding = (curField->getFlags() & RTTI_Flag_WeakRef) == 0 && !objToDecode.isDecoded;
 							if (needsDecoding)
 							{
-								decodeInternal(objToDecode.object, objToDecode.serializedObject);
-								objToDecode.isDecoded = true;
+								if (objToDecode.decodeInProgress)
+								{
+									LOGWRN("Detected a circular reference when decoding. Referenced object's fields " \
+										"will be resolved in an undefined order (i.e. one of the objects will not " \
+										"be fully deserialized when assigned to its field). Use RTTI_Flag_WeakRef to " \
+										"get rid of this warning and tell the system which of the objects is allowed " \
+										"to be deserialized after it is assigned to its field.");
+								}
+								else
+								{
+									objToDecode.decodeInProgress = true;
+									decodeInternal(objToDecode.object, objToDecode.serializedObject);
+									objToDecode.decodeInProgress = false;
+									objToDecode.isDecoded = true;
+								}
 							}
 
 							curField->setValue(object.get(), objToDecode.object);