// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Content/Asset.h" /// /// Asset reference utility that doesn't add reference to that asset. Handles asset unload event. /// API_CLASS(InBuild) class WeakAssetReferenceBase { public: typedef Delegate<> EventType; protected: Asset* _asset; public: /// /// The asset unloading event (should cleanup refs to it). /// EventType Unload; public: /// /// Initializes a new instance of the class. /// WeakAssetReferenceBase() : _asset(nullptr) { } /// /// Finalizes an instance of the class. /// ~WeakAssetReferenceBase() { if (_asset) { _asset->OnUnloaded.Unbind(this); _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->OnUnloaded.Unbind(this); _asset = e = asset; if (e) e->OnUnloaded.Bind(this); } } void OnAssetUnloaded(Asset* asset) { ASSERT(_asset == asset); Unload(); Unlink(); } }; /// /// Asset reference utility that doesn't add reference to that asset. Handles asset unload event. /// template API_CLASS(InBuild) class WeakAssetReference : public WeakAssetReferenceBase { public: /// /// Initializes a new instance of the class. /// WeakAssetReference() : WeakAssetReferenceBase() { } /// /// Initializes a new instance of the class. /// /// The asset to set. WeakAssetReference(T* asset) : WeakAssetReferenceBase() { OnSet(asset); } /// /// Initializes a new instance of the class. /// /// The other. WeakAssetReference(const WeakAssetReference& other) { OnSet(other.Get()); } /// /// Finalizes an instance of the class. /// ~WeakAssetReference() { } public: FORCE_INLINE WeakAssetReference& operator=(const WeakAssetReference& other) { OnSet(other.Get()); return *this; } FORCE_INLINE WeakAssetReference& operator=(T* other) { OnSet(other); return *this; } FORCE_INLINE WeakAssetReference& 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 WeakAssetReference& 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); } };