Jelajahi Sumber

Added a method for finding all resource dependencies in an object

Marko Pintera 11 tahun lalu
induk
melakukan
3bcd068db3

+ 2 - 0
BansheeCore/BansheeCore.vcxproj

@@ -360,6 +360,7 @@
     <ClInclude Include="Include\BsTextData.h" />
     <ClInclude Include="Include\BsTimerQuery.h" />
     <ClInclude Include="Include\BsTransientMesh.h" />
+    <ClInclude Include="Include\BsUtility.h" />
     <ClInclude Include="Include\BsUUID.h" />
     <ClInclude Include="Include\BsVertexBuffer.h" />
     <ClInclude Include="Include\BsGpuProgramManager.h" />
@@ -483,6 +484,7 @@
     <ClCompile Include="Source\BsTextData.cpp" />
     <ClCompile Include="Source\BsTimerQuery.cpp" />
     <ClCompile Include="Source\BsTransientMesh.cpp" />
+    <ClCompile Include="Source\BsUtility.cpp" />
     <ClCompile Include="Source\BsUUID.cpp" />
     <ClCompile Include="Source\BsVertexBuffer.cpp" />
     <ClCompile Include="Source\BsGpuProgramManager.cpp" />

+ 9 - 0
BansheeCore/BansheeCore.vcxproj.filters

@@ -88,6 +88,9 @@
     <Filter Include="Source Files\RenderAPI">
       <UniqueIdentifier>{e0bdc5fc-afd1-46f9-9e3e-f85ca3e220b8}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Source Files\Utility">
+      <UniqueIdentifier>{0d63b345-0a58-4df2-9d01-f4da53fc40c9}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\BsRenderStats.h">
@@ -522,6 +525,9 @@
     <ClInclude Include="Include\BsResourceListenerManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsUtility.h">
+      <Filter>Header Files\Utility</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -824,5 +830,8 @@
     <ClCompile Include="Source\BsResourceListenerManager.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsUtility.cpp">
+      <Filter>Source Files\Utility</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 33 - 0
BansheeCore/Include/BsUtility.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "BsCorePrerequisites.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Static class containing various utility methods that do not
+	 *			fit anywhere else.
+	 */
+	class BS_CORE_EXPORT Utility
+	{
+	public:
+		/**
+		 * @brief	Finds all resources referenced by the specified object.
+		 *
+		 * @param	object		Object to search for resource dependencies.
+		 * @param	recursive	Determines whether or not child objects will also be
+		 *						searched (if object has any children).
+		 *
+		 * @returns	A list of unique, non-null resources.
+		 */
+		static Vector<HResource> findResourceDependencies(IReflectable& object, bool recursive = true);
+
+	private:
+		/**
+		 * @brief	Helper method for for recursion when finding resource dependencies.
+		 *
+		 * @see	findDependencies
+		 */
+		static void findResourceDependenciesInternal(IReflectable& object, bool recursive, Map<String, HResource>& dependencies);
+	};
+}

+ 96 - 0
BansheeCore/Source/BsUtility.cpp

@@ -0,0 +1,96 @@
+#include "BsUtility.h"
+#include "BsRTTIType.h"
+
+namespace BansheeEngine
+{
+	Vector<HResource> Utility::findResourceDependencies(IReflectable& obj, bool recursive)
+	{
+		Map<String, HResource> dependencies;
+		findResourceDependenciesInternal(obj, recursive, dependencies);
+
+		Vector<HResource> dependencyList(dependencies.size());
+		UINT32 i = 0;
+		for (auto& entry : dependencies)
+		{
+			dependencyList[i] = entry.second;
+			i++;
+		}
+
+		return dependencyList;
+	}
+
+	void Utility::findResourceDependenciesInternal(IReflectable& obj, bool recursive, Map<String, HResource>& dependencies)
+	{
+		RTTITypeBase* rtti = obj.getRTTI();
+		rtti->onDeserializationStarted(&obj);
+
+		UINT32 numFields = rtti->getNumFields();
+		for (UINT32 i = 0; i < numFields; i++)
+		{
+			RTTIField* field = rtti->getField(i);
+
+			if (field->isReflectableType())
+			{
+				RTTIReflectableFieldBase* reflectableField = static_cast<RTTIReflectableFieldBase*>(field);
+
+				if (reflectableField->getType()->getRTTIId() == TID_ResourceHandle)
+				{
+					if (reflectableField->isArray())
+					{
+						UINT32 numElements = reflectableField->getArraySize(&obj);
+						for (UINT32 j = 0; i < numElements; j++)
+						{
+							HResource resource = (HResource&)reflectableField->getArrayValue(&obj, j);
+							if (resource != nullptr)
+								dependencies[resource.getUUID()] = resource;
+						}
+					}
+					else
+					{
+						HResource resource = (HResource&)reflectableField->getValue(&obj);
+						if (resource != nullptr)
+							dependencies[resource.getUUID()] = resource;
+					}
+				}
+				else if (recursive)
+				{
+					if (reflectableField->isArray())
+					{
+						UINT32 numElements = reflectableField->getArraySize(&obj);
+						for (UINT32 j = 0; i < numElements; j++)
+						{
+							IReflectable& childObj = reflectableField->getArrayValue(&obj, j);
+							findResourceDependenciesInternal(childObj, true, dependencies);
+						}
+					}
+					else
+					{
+						IReflectable& childObj = reflectableField->getValue(&obj);
+						findResourceDependenciesInternal(childObj, true, dependencies);
+					}
+				}
+			}
+			else if (field->isReflectablePtrType() && recursive)
+			{
+				RTTIReflectablePtrFieldBase* reflectablePtrField = static_cast<RTTIReflectablePtrFieldBase*>(field);
+
+				if (reflectablePtrField->isArray())
+				{
+					UINT32 numElements = reflectablePtrField->getArraySize(&obj);
+					for (UINT32 j = 0; i < numElements; j++)
+					{
+						SPtr<IReflectable> childObj = reflectablePtrField->getArrayValue(&obj, j);
+						findResourceDependenciesInternal(*childObj, true, dependencies);
+					}
+				}
+				else
+				{
+					SPtr<IReflectable> childObj = reflectablePtrField->getValue(&obj);
+					findResourceDependenciesInternal(*childObj, true, dependencies);
+				}
+			}
+		}
+
+		rtti->onDeserializationEnded(&obj);
+	}
+}

+ 2 - 1
BansheeUtility/Include/BsRTTIField.h

@@ -89,7 +89,8 @@ namespace BansheeEngine
 		bool isDataBlockType() { return mType == SerializableFT_DataBlock; }
 		bool isReflectableType() { return mType == SerializableFT_Reflectable; }
 		bool isReflectablePtrType() { return mType == SerializableFT_ReflectablePtr; }
-		
+		bool isArray() const { return mIsVectorType; }
+
 		/**
 		 * @brief	Returns flags that were set in the field meta-data.
 		 */

+ 17 - 11
TODO.txt

@@ -1,8 +1,5 @@
 --------- ALL LONG TERM TASKS / FIXES BELONG TO GOOGLE DOCS: ImplementationTODO OR PossibleImprovements ----------
 
- New issues:
-  - Since Mesh refactor when I select/deselect a gizmo the entire render texture flashes white for one frame (might be related to RT refactor instead)
-
 1. Make sure shader create() methods returns a HShader
 2. Make sure material uses HShader
 3. Make sure material listens for HShader load event (derives from IResourceListener)
@@ -12,12 +9,26 @@
 
 See GDrive/Resources doc for resources refactor
 
+ManagedComponent deserialization IS WRONG
+ - I register the component with ScriptGameObjectManager during deserialization when its ID is wrong
+
+Add a special mode to GameObjectManager that is active during deserialization
+ - Any handle or GameObject deserialized when its active will use a special mapping for resolving/updating IDs
+  - THIS doesn't really work because I might need to resolve a handle before the object is deserialized
+  - But could I add entries to the map from both handle and object regardless of which is resolved first?
+    - YES - This gets rid of the need for post-processing of GameObject, solves my ScriptComponent deserialization issue and allows me to deserialize managed fields on demand
+
+Modify managed serialization so that deserialization/serialization happens per field instead of in deserialize/serialize methods during pre- and post-processing step.
+ - Make sure to fix the GameObjectManager delayed deserialization issue first
+ - When generating SerializableFieldInfo generate mFieldGlobalIdx (index that takes into consideration any base classes)
+   - Then when de/serializing use that index to get field info and call get/setFieldData accordingly in RTTI getter/setter directly
+   - How to use it when deserializing though?
+     - Ensure that ManagedObjectInfo is deserialized first. Since this is an unclear dependency make sure to add asserts so when it fails it is clear why.
+     - Then use that to look up field during runtime
+
 I can get mono errors by checking g_print calls in goutput.c
  - Calling thunks incorrectly can cause those weird errors with no real callstack
 
-Mouse wrap doesn't seem to work the first time
-If you release mouse outside the window the handle doesn't get deselected and wrap remains active
-
 Other:
 Window resize end callback
 Add cutoff plane when rendering discs for rotation handle.
@@ -29,11 +40,6 @@ Add ProjectWindow and HierarchyWindow to C#
  - Make TreeViews a C# element?
 Set up a default layout and save it
 
-Test:
- - If cursor wrap works
- - If handles work when dragged outside of scene window
- - If handle is properly released if mouse up is pressed outside
-
 -----------------
 
 Need a way to drag and drop items from Scene tree view to Scene view