// Copyright (c) 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 = nullptr; public: /// /// The asset unloading event (should cleanup refs to it). /// EventType Unload; public: NON_COPYABLE(WeakAssetReferenceBase); /// /// Initializes a new instance of the class. /// WeakAssetReferenceBase() = default; /// /// Finalizes an instance of the class. /// ~WeakAssetReferenceBase(); public: /// /// Gets 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). /// FORCE_INLINE MObject* GetManagedInstance() const { return _asset ? _asset->GetOrCreateManagedInstance() : nullptr; } /// /// Gets the asset property value as string. /// String ToString() const; protected: void OnSet(Asset* asset); void OnUnloaded(Asset* asset); }; /// /// 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()); } WeakAssetReference(WeakAssetReference&& other) { OnSet(other.Get()); other.OnSet(nullptr); } WeakAssetReference& operator=(WeakAssetReference&& other) { if (&other != this) { OnSet(other.Get()); other.OnSet(nullptr); } return *this; } /// /// 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((Asset*)other); return *this; } FORCE_INLINE WeakAssetReference& operator=(const Guid& id) { OnSet((Asset*)::LoadAsset(id, T::TypeInitializer)); return *this; } FORCE_INLINE bool operator==(T* other) const { return _asset == other; } FORCE_INLINE bool operator==(const WeakAssetReference& other) const { return _asset == other._asset; } /// /// Implicit conversion to the bool. /// FORCE_INLINE operator T*() const { return (T*)_asset; } /// /// Implicit conversion to the asset. /// FORCE_INLINE operator bool() const { return _asset != nullptr; } /// /// Implicit conversion to the asset. /// FORCE_INLINE T* operator->() const { return (T*)_asset; } /// /// Gets the asset. /// FORCE_INLINE T* Get() const { return (T*)_asset; } /// /// Gets the asset as a given type (static cast). /// template FORCE_INLINE U* As() const { return (U*)_asset; } public: /// /// Sets the asset reference. /// /// The asset. void Set(T* asset) { OnSet(asset); } }; template uint32 GetHash(const WeakAssetReference& key) { return GetHash(key.GetID()); }