// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Content/Asset.h" /// /// Asset reference utility. Keeps reference to the linked asset object and handles load/unload events. /// class FLAXENGINE_API AssetReferenceBase { public: typedef Delegate<> EventType; protected: Asset* _asset; public: /// /// The asset loaded event (fired when asset gets loaded or is already loaded after change). /// EventType Loaded; /// /// The asset unloading event (should cleanup refs to it). /// EventType Unload; /// /// Action fired when field gets changed (link a new asset or change to the another value). /// EventType Changed; public: /// /// Initializes a new instance of the class. /// AssetReferenceBase() : _asset(nullptr) { } /// /// Finalizes an instance of the class. /// ~AssetReferenceBase() { if (_asset) { _asset->OnLoaded.Unbind(this); _asset->OnUnloaded.Unbind(this); _asset->RemoveReference(); _asset = nullptr; } } public: /// /// Gets the asset ID or Guid::Empty if not set. /// /// The asset ID or Guid::Empty if not set. FORCE_INLINE Guid GetID() const { return _asset ? _asset->GetID() : Guid::Empty; } /// /// Gets managed instance object (or null if no asset set). /// /// Mono managed object FORCE_INLINE MonoObject* GetManagedInstance() const { return _asset ? _asset->GetOrCreateManagedInstance() : nullptr; } /// /// Clears the asset reference. /// FORCE_INLINE void Unlink() { OnSet(nullptr); } /// /// Gets the asset property value as string. /// /// The string. String ToString() const { static String NullStr = TEXT(""); return _asset ? _asset->ToString() : NullStr; } protected: void OnSet(Asset* asset) { auto e = _asset; if (e != asset) { if (e) { e->OnLoaded.Unbind(this); e->OnUnloaded.Unbind(this); e->RemoveReference(); } _asset = e = asset; if (e) { e->AddReference(); e->OnLoaded.Bind(this); e->OnUnloaded.Bind(this); } Changed(); if (e && e->IsLoaded()) Loaded(); } } void OnAssetLoaded(Asset* asset) { if (_asset == asset) { Loaded(); } } void OnAssetUnloaded(Asset* asset) { if (_asset == asset) { Unload(); Unlink(); } } }; /// /// Asset reference utility. Keeps reference to the linked asset object and handles load/unload events. /// template API_CLASS(InBuild) class AssetReference : public AssetReferenceBase { public: typedef T AssetType; typedef AssetReference Type; public: /// /// Initializes a new instance of the class. /// AssetReference() { } /// /// Initializes a new instance of the class. /// /// The asset to set. AssetReference(T* asset) { OnSet(asset); } /// /// Initializes a new instance of the class. /// /// The other. AssetReference(const AssetReference& other) { OnSet(other.Get()); } /// /// Finalizes an instance of the class. /// ~AssetReference() { } public: FORCE_INLINE AssetReference& operator=(const AssetReference& other) { OnSet(other.Get()); return *this; } FORCE_INLINE AssetReference& operator=(T* other) { OnSet(other); return *this; } FORCE_INLINE AssetReference& operator=(const Guid& id) { OnSet((T*)LoadAsset(id, T::TypeInitializer)); return *this; } FORCE_INLINE bool operator==(T* other) { return _asset == other; } FORCE_INLINE bool operator==(const AssetReference& other) { return _asset == other._asset; } FORCE_INLINE bool operator!=(T* other) { return _asset != other; } FORCE_INLINE bool operator!=(const AssetReference& other) { return _asset != other._asset; } /// /// Implicit conversion to the bool. /// /// The asset. FORCE_INLINE operator T*() const { return (T*)_asset; } /// /// Implicit conversion to the asset. /// /// True if asset has been set, otherwise false. FORCE_INLINE operator bool() const { return _asset != nullptr; } /// /// Implicit conversion to the asset. /// /// The asset. FORCE_INLINE T* operator->() const { return (T*)_asset; } /// /// Gets the asset. /// /// The asset. FORCE_INLINE T* Get() const { return (T*)_asset; } /// /// Gets the asset as a given type (static cast). /// /// The asset. template FORCE_INLINE U* As() const { return (U*)_asset; } public: /// /// Sets the asset reference. /// /// The asset. void Set(T* asset) { OnSet(asset); } };