#pragma once #include "BsScriptEnginePrerequisites.h" #include "BsScriptObject.h" namespace BansheeEngine { /** * @brief Types of resources accessible from script code. */ enum class ScriptResourceType // Note: Must be the same as C# enum ScriptResourceType { Texture, SpriteTexture, Mesh, Font, Shader, ShaderInclude, Material, Prefab, PlainText, ScriptCode, StringTable, GUISkin, Undefined }; /** * @brief Base class for all resource interop objects. */ class BS_SCR_BE_EXPORT ScriptResourceBase : public PersistentScriptObjectBase { public: /** * @brief Returns a generic handle to the internal wrapped resource. */ virtual HResource getGenericHandle() const = 0; /** * @brief Sets the internal resource this object wraps. */ virtual void setResource(const HResource& resource) = 0; /** * @copydoc ScriptObjectBase::beginRefresh */ virtual ScriptObjectBackup beginRefresh() override; /** * @copydoc ScriptObjectBase::endRefresh */ virtual void endRefresh(const ScriptObjectBackup& backupData) override; protected: friend class ScriptResourceManager; ScriptResourceBase(MonoObject* instance); virtual ~ScriptResourceBase() {} /** * @brief Triggered by the script resource managed when the native resource handle this object point to has * been destroyed. */ virtual void notifyResourceDestroyed() { } /** * @brief Destroys the interop object, unless refresh is in progress in which case it is just prepared * for re-creation. */ void destroy(); bool mRefreshInProgress; }; /** * @brief Base class for a specific resource's interop object. */ template class BS_SCR_BE_EXPORT TScriptResource : public ScriptObject { public: /** * @copydoc ScriptResourceBase::getGenericHandle */ HResource getGenericHandle() const override { return mResource; } /** * @copydoc ScriptResourceBase::setResource */ void setResource(const HResource& resource) override { mResource = static_resource_cast(resource); } /** * @brief Returns a handle to the internal wrapped resource. */ const ResourceHandle& getHandle() const { return mResource; } protected: friend class ScriptResourceManager; TScriptResource(MonoObject* instance, const ResourceHandle& resource) :ScriptObject(instance), mResource(resource) { mManagedHandle = mono_gchandle_new(instance, false); BS_DEBUG_ONLY(mHandleValid = true); } virtual ~TScriptResource() {} /** * @copydoc ScriptObjectBase::endRefresh */ virtual void endRefresh(const ScriptObjectBackup& backupData) override { BS_ASSERT(!mHandleValid); mManagedHandle = mono_gchandle_new(mManagedInstance, false); ScriptObject::endRefresh(backupData); } /** * @copydoc ScriptObjectBase::notifyResourceDestroyed */ void notifyResourceDestroyed() override { mono_gchandle_free(mManagedHandle); BS_DEBUG_ONLY(mHandleValid = false); } /** * @copydoc ScriptObjectBase::_onManagedInstanceDeleted */ void _onManagedInstanceDeleted() override { mono_gchandle_free(mManagedHandle); BS_DEBUG_ONLY(mHandleValid = false); destroy(); } ResourceHandle mResource; uint32_t mManagedHandle; BS_DEBUG_ONLY(bool mHandleValid); }; /** * @brief Interop class between C++ & CLR for Resource. */ class BS_SCR_BE_EXPORT ScriptResource : public ScriptObject { public: SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "Resource") /** * @brief Converts a RTTI id belonging to a resource type into a ScriptResourceType. */ static ScriptResourceType getTypeFromTypeId(UINT32 typeId); /** * @brief Converts a ScriptResourceType into a RTTI id belonging to that resource type. */ static UINT32 getTypeIdFromType(ScriptResourceType type); private: ScriptResource(MonoObject* instance) :ScriptObject(instance) { } /************************************************************************/ /* CLR HOOKS */ /************************************************************************/ static MonoString* internal_getName(ScriptResourceBase* nativeInstance); static MonoString* internal_getUUID(ScriptResourceBase* nativeInstance); }; }