// Copyright (c) 2012-2023 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 = nullptr; 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: NON_COPYABLE(AssetReferenceBase); /// /// Initializes a new instance of the class. /// AssetReferenceBase() = default; /// /// Finalizes an instance of the class. /// ~AssetReferenceBase(); 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 OnLoaded(Asset* asset); void OnUnloaded(Asset* asset); }; /// /// 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()); } AssetReference(AssetReference&& other) { OnSet(other.Get()); other.OnSet(nullptr); } AssetReference& operator=(AssetReference&& other) { if (&other != this) { OnSet(other.Get()); other.OnSet(nullptr); } return *this; } /// /// 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) const { return _asset == other; } FORCE_INLINE bool operator==(const AssetReference& other) const { return _asset == other._asset; } FORCE_INLINE bool operator!=(T* other) const { return _asset != other; } FORCE_INLINE bool operator!=(const AssetReference& 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 AssetReference& key) { return GetHash(key.GetID()); }