Quellcode durchsuchen

Added a way to attach editor-only data to resources

BearishSun vor 9 Jahren
Ursprung
Commit
0b4c5846dc

+ 9 - 0
Source/BansheeEditor/Include/BsProjectLibrary.h

@@ -205,6 +205,15 @@ namespace BansheeEngine
 		 */
 		void setIncludeInBuild(const Path& path, bool force);
 
+		/** 
+		 * Assigns a non-specific user data object to the resource at the specified path. 
+		 * 
+		 * @param[in]	path		Path to the resource to modify, absolute or relative to resources folder.
+		 * @param[in]	userData	User data to assign to the resource, which can later be retrieved from the resource's
+		 *							meta-data as needed. 
+		 */
+		void setUserData(const Path& path, const SPtr<IReflectable>& userData);
+
 		/**
 		 * Finds all top-level resource entries that should be included in a build. Values returned by this method are
 		 * transient, they may be destroyed on any following ProjectLibrary call.

+ 9 - 2
Source/BansheeEditor/Include/BsProjectResourceMeta.h

@@ -44,6 +44,12 @@ namespace BansheeEngine
 		/**	Returns the RTTI type ID of the resource this object is referencing. */
 		UINT32 getTypeID() const { return mTypeId; }
 
+		/** 
+		 * Returns additional data attached to the resource meta by the user. This is non-specific data and can contain
+		 * anything the user requires. 
+		 */
+		SPtr<IReflectable> getUserData() const { return mUserData; }
+
 	private:
 		friend class ProjectLibrary;
 
@@ -51,6 +57,7 @@ namespace BansheeEngine
 		String mUUID;
 		SPtr<ResourceMetaData> mResourceMeta;
 		UINT32 mTypeId;
+		SPtr<IReflectable> mUserData;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/
@@ -62,7 +69,7 @@ namespace BansheeEngine
 	public:
 		friend class ProjectResourceMetaRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
+		RTTITypeBase* getRTTI() const override;	
 	};
 
 	/**	
@@ -129,7 +136,7 @@ namespace BansheeEngine
 	public:
 		friend class ProjectFileMetaRTTI;
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
+		RTTITypeBase* getRTTI() const override;	
 	};
 
 	/** @} */

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

@@ -23,6 +23,7 @@ namespace BansheeEngine
 			BS_RTTI_MEMBER_PLAIN(mUUID, 1)
 			BS_RTTI_MEMBER_PLAIN(mTypeId, 2)
 			BS_RTTI_MEMBER_REFLPTR(mResourceMeta, 3)
+			BS_RTTI_MEMBER_REFLPTR(mUserData, 4)
 		BS_END_RTTI_MEMBERS
 	public:
 		ProjectResourceMetaRTTI()

+ 31 - 0
Source/BansheeEditor/Source/BsProjectLibrary.cpp

@@ -1141,6 +1141,37 @@ namespace BansheeEngine
 		fs.encode(resEntry->meta.get());
 	}
 
+	void ProjectLibrary::setUserData(const Path& path, const SPtr<IReflectable>& userData)
+	{
+		LibraryEntry* entry = findEntry(path);
+
+		if (entry == nullptr || entry->type == LibraryEntryType::Directory)
+			return;
+
+		FileEntry* fileEntry = static_cast<FileEntry*>(entry);
+		if (fileEntry->meta == nullptr)
+			return;
+
+		SPtr<ProjectResourceMeta> resMeta;
+		auto& resourceMetas = fileEntry->meta->getResourceMetaData();
+		for (auto& resMetaEntry : resourceMetas)
+		{
+			if (resMeta->getUniqueName() == path.getWTail())
+				resMeta = resMetaEntry;
+		}
+
+		if (resMeta == nullptr)
+			return;
+
+		resMeta->mUserData = userData;
+
+		Path metaPath = fileEntry->path;
+		metaPath.setFilename(metaPath.getWFilename() + L".meta");
+
+		FileEncoder fs(metaPath);
+		fs.encode(fileEntry->meta.get());
+	}
+
 	Vector<ProjectLibrary::FileEntry*> ProjectLibrary::getResourcesForBuild() const
 	{
 		Vector<FileEntry*> output;

+ 1 - 0
Source/BansheeUtility/CMakeSources.cmake

@@ -112,6 +112,7 @@ set(BS_BANSHEEUTILITY_SRC_DEBUG
 
 set(BS_BANSHEEUTILITY_INC_RTTI
 	"Include/BsSerializedObjectRTTI.h"
+	"Include/BsIReflectableRTTI.h"
 )
 
 set(BS_BANSHEEUTILITY_INC_ALLOCATORS

+ 2 - 1
Source/BansheeUtility/Include/BsFwdDeclUtil.h

@@ -112,6 +112,7 @@ namespace BansheeEngine
 		TID_SerializedSubObject = 65,
 		TID_UnorderedSet = 66,
 		TID_SerializedDataBlock = 67,
-		TID_Flags = 68
+		TID_Flags = 68,
+		TID_IReflectable = 69
 	};
 }

+ 3 - 0
Source/BansheeUtility/Include/BsIReflectable.h

@@ -78,6 +78,9 @@ namespace BansheeEngine
 		 */
 		static void _checkForCircularReferences();
 
+		/** Returns an interface you can use to access class' Run Time Type Information. */
+		static RTTITypeBase* getRTTIStatic();
+
 		/** @} */
 
 	protected:

+ 40 - 0
Source/BansheeUtility/Include/BsIReflectableRTTI.h

@@ -0,0 +1,40 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsPrerequisitesUtil.h"
+#include "BsRTTIType.h"
+
+namespace BansheeEngine
+{
+	/** @cond RTTI */
+	/** @addtogroup RTTI-Impl-Utility
+	 *  @{
+	 */
+
+	class BS_UTILITY_EXPORT IReflectableRTTI : public RTTIType <IReflectable, IReflectable, IReflectableRTTI>
+	{
+	public:
+		IReflectableRTTI()
+		{ }
+
+		const String& getRTTIName() override
+		{
+			static String name = "IReflectable";
+			return name;
+		}
+
+		UINT32 getRTTIId() override
+		{
+			return TID_IReflectable;
+		}
+
+		SPtr<IReflectable> newRTTIObject() override
+		{
+			return nullptr;
+		}
+	};
+
+	/** @} */
+	/** @endcond */
+}

+ 6 - 0
Source/BansheeUtility/Source/BsIReflectable.cpp

@@ -3,6 +3,7 @@
 #include "BsIReflectable.h"
 #include "BsRTTIType.h"
 #include "BsException.h"
+#include "BsIReflectableRTTI.h"
 
 namespace BansheeEngine
 {
@@ -120,4 +121,9 @@ namespace BansheeEngine
 	{
 		return getRTTI()->getRTTIName();
 	}
+
+	RTTITypeBase* IReflectable::getRTTIStatic()
+	{
+		return IReflectableRTTI::instance();
+	}
 }

+ 22 - 0
Source/MBansheeEditor/Windows/Library/ProjectLibrary.cs

@@ -289,6 +289,17 @@ namespace BansheeEditor
             Internal_SetIncludeInBuild(path, include);
         }
 
+        /// <summary>
+        /// Assigns a non-specific editor data object to the resource at the specified path. 
+        /// </summary>
+        /// <param name="path">Path to the resource to modify, absolute or relative to resources folder.</param>
+        /// <param name="userData">Data to assign to the resource, which can later be retrieved from the resource's
+        /// meta-data as needed. </param>
+        public static void SetEditorData(string path, object userData)
+        {
+            Internal_SetEditorData(path, userData);
+        }
+
         /// <summary>
         /// Triggers reimport for queued resource. Should be called once per frame.
         /// </summary>
@@ -437,6 +448,9 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetIncludeInBuild(string path, bool force);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetEditorData(string path, object userData);
     }
 
     /// <summary>
@@ -563,6 +577,11 @@ namespace BansheeEditor
         /// </summary>
         public ResourceType ResType { get { return Internal_GetResourceType(mCachedPtr); } }
 
+        /// <summary>
+        /// Non-specific data assigned to the resource, available in editor only.
+        /// </summary>
+        public object EditorData { get { return Internal_GetEditorData(mCachedPtr); } }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern string Internal_GetUUID(IntPtr thisPtr);
 
@@ -574,6 +593,9 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern ResourceType Internal_GetResourceType(IntPtr thisPtr);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern object Internal_GetEditorData(IntPtr thisPtr);
     }
 
     /** @} */

+ 2 - 0
Source/SBansheeEditor/Include/BsScriptProjectLibrary.h

@@ -81,6 +81,7 @@ namespace BansheeEngine
 		static void internal_Copy(MonoString* source, MonoString* destination, bool overwrite);
 		static MonoString* internal_GetResourceFolder();
 		static void internal_SetIncludeInBuild(MonoString* path, bool include);
+		static void internal_SetEditorData(MonoString* path, MonoObject* userData);
 	};
 
 	/**	Base class for C++/CLR interop objects used for wrapping LibraryEntry implementations. */
@@ -172,6 +173,7 @@ namespace BansheeEngine
 		static MonoString* internal_GetSubresourceName(ScriptResourceMeta* thisPtr);
 		static MonoObject* internal_GetIcon(ScriptResourceMeta* thisPtr);
 		static ScriptResourceType internal_GetResourceType(ScriptResourceMeta* thisPtr);
+		static MonoObject* internal_GetEditorData(ScriptResourceMeta* thisPtr);
 	};
 
 	/** @} */

+ 37 - 6
Source/SBansheeEditor/Source/BsScriptProjectLibrary.cpp

@@ -2,22 +2,18 @@
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsScriptProjectLibrary.h"
 #include "BsScriptMeta.h"
-#include "BsMonoField.h"
 #include "BsMonoClass.h"
 #include "BsMonoMethod.h"
-#include "BsMonoManager.h"
 #include "BsMonoUtil.h"
 #include "BsScriptResource.h"
 #include "BsResources.h"
-#include "BsResource.h"
 #include "BsProjectResourceMeta.h"
 #include "BsScriptResourceManager.h"
 #include "BsScriptTexture2D.h"
-#include "BsScriptSpriteTexture.h"
-#include "BsScriptFont.h"
 #include "BsScriptImportOptions.h"
 #include "BsEditorApplication.h"
-#include "BsPath.h"
+#include "BsManagedSerializableObject.h"
+#include "BsRTTIType.h"
 
 using namespace std::placeholders;
 
@@ -56,6 +52,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_Copy", &ScriptProjectLibrary::internal_Copy);
 		metaData.scriptClass->addInternalCall("Internal_GetResourceFolder", &ScriptProjectLibrary::internal_GetResourceFolder);
 		metaData.scriptClass->addInternalCall("Internal_SetIncludeInBuild", &ScriptProjectLibrary::internal_SetIncludeInBuild);
+		metaData.scriptClass->addInternalCall("Internal_SetEditorData", &ScriptProjectLibrary::internal_SetEditorData);
 
 		OnEntryAddedThunk = (OnEntryChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnEntryAdded", 1)->getThunk();
 		OnEntryRemovedThunk = (OnEntryChangedThunkDef)metaData.scriptClass->getMethod("Internal_DoOnEntryRemoved", 1)->getThunk();
@@ -268,6 +265,22 @@ namespace BansheeEngine
 		gProjectLibrary().setIncludeInBuild(pathNative, include);
 	}
 
+	void ScriptProjectLibrary::internal_SetEditorData(MonoString* path, MonoObject* userData)
+	{
+		Path pathNative = MonoUtil::monoToWString(path);
+
+		if(userData == nullptr)
+		{
+			gProjectLibrary().setUserData(pathNative, nullptr);
+			return;
+		}
+
+		SPtr<ManagedSerializableObject> serializedUserData = ManagedSerializableObject::createFromExisting(userData);
+		serializedUserData->serialize();
+
+		gProjectLibrary().setUserData(pathNative, serializedUserData);
+	}
+
 	void ScriptProjectLibrary::startUp()
 	{
 		mOnEntryAddedConn = gProjectLibrary().onEntryAdded.connect(std::bind(&ScriptProjectLibrary::onEntryAdded, _1));
@@ -496,6 +509,7 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetSubresourceName", &ScriptResourceMeta::internal_GetSubresourceName);
 		metaData.scriptClass->addInternalCall("Internal_GetIcon", &ScriptResourceMeta::internal_GetIcon);
 		metaData.scriptClass->addInternalCall("Internal_GetResourceType", &ScriptResourceMeta::internal_GetResourceType);
+		metaData.scriptClass->addInternalCall("Internal_GetEditorData", &ScriptResourceMeta::internal_GetEditorData);
 	}
 
 	MonoString* ScriptResourceMeta::internal_GetUUID(ScriptResourceMeta* thisPtr)
@@ -518,4 +532,21 @@ namespace BansheeEngine
 	{
 		return ScriptResource::getTypeFromTypeId(thisPtr->mMeta->getTypeID());
 	}
+
+	MonoObject* ScriptResourceMeta::internal_GetEditorData(ScriptResourceMeta* thisPtr)
+	{
+		SPtr<IReflectable> userData = thisPtr->mMeta->getUserData();
+		if (userData == nullptr)
+			return nullptr;
+
+		if (!rtti_is_of_type<ManagedSerializableObject>(userData.get()))
+			return nullptr;
+
+		SPtr<ManagedSerializableObject> userDataObj = std::static_pointer_cast<ManagedSerializableObject>(userData);
+		userDataObj->deserialize();
+		MonoObject* instance = userDataObj->getManagedInstance();
+		userDataObj->serialize();
+
+		return instance;
+	}
 }