// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Content/Asset.h" /// /// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it). /// class FLAXENGINE_API SoftAssetReferenceBase { protected: Asset* _asset = nullptr; Guid _id = Guid::Empty; public: /// /// Action fired when field gets changed (link a new asset or change to the another value). /// Delegate<> Changed; public: NON_COPYABLE(SoftAssetReferenceBase); /// /// Initializes a new instance of the class. /// SoftAssetReferenceBase() = default; /// /// Finalizes an instance of the class. /// ~SoftAssetReferenceBase() { } public: /// /// Gets the asset ID or Guid::Empty if not set. /// FORCE_INLINE Guid GetID() const { return _id; } /// /// Gets the asset property value as string. /// String ToString() const; protected: void OnSet(Asset* asset); void OnSet(const Guid& id); void OnResolve(const ScriptingTypeHandle& type); void OnUnloaded(Asset* asset); }; /// /// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it). /// template API_CLASS(InBuild) class SoftAssetReference : public SoftAssetReferenceBase { public: typedef T AssetType; typedef SoftAssetReference Type; public: /// /// Initializes a new instance of the class. /// SoftAssetReference() { } /// /// Initializes a new instance of the class. /// /// The asset to set. SoftAssetReference(T* asset) { OnSet(asset); } /// /// Initializes a new instance of the class. /// /// The other. SoftAssetReference(const SoftAssetReference& other) { OnSet(other.GetID()); } SoftAssetReference(SoftAssetReference&& other) { OnSet(other.GetID()); other.OnSet(Guid::Empty); } /// /// Finalizes an instance of the class. /// ~SoftAssetReference() { } public: FORCE_INLINE bool operator==(T* other) const { return Get() == other; } FORCE_INLINE bool operator==(const SoftAssetReference& other) const { return GetID() == other.GetID(); } FORCE_INLINE bool operator!=(T* other) const { return Get() != other; } FORCE_INLINE bool operator!=(const SoftAssetReference& other) const { return GetID() != other.GetID(); } SoftAssetReference& operator=(const SoftAssetReference& other) { if (this != &other) OnSet(other.GetID()); return *this; } SoftAssetReference& operator=(SoftAssetReference&& other) { if (this != &other) { OnSet(other.GetID()); other.OnSet(nullptr); } return *this; } FORCE_INLINE SoftAssetReference& operator=(const T& other) { OnSet(&other); return *this; } FORCE_INLINE SoftAssetReference& operator=(T* other) { OnSet(other); return *this; } FORCE_INLINE SoftAssetReference& operator=(const Guid& id) { OnSet(id); return *this; } FORCE_INLINE operator T*() const { return (T*)Get(); } FORCE_INLINE operator bool() const { return Get() != nullptr; } FORCE_INLINE T* operator->() const { return (T*)Get(); } template FORCE_INLINE U* As() const { return static_cast(Get()); } public: /// /// Gets the asset (or null if unassigned). /// T* Get() const { if (!_asset) const_cast(this)->OnResolve(T::TypeInitializer); return (T*)_asset; } /// /// Gets managed instance object (or null if no asset linked). /// MObject* GetManagedInstance() const { auto asset = Get(); return asset ? asset->GetOrCreateManagedInstance() : nullptr; } /// /// Determines whether asset is assigned and managed instance of the asset is alive. /// bool HasManagedInstance() const { auto asset = Get(); return asset && asset->HasManagedInstance(); } /// /// Gets the managed instance object or creates it if missing or null if not assigned. /// MObject* GetOrCreateManagedInstance() const { auto asset = Get(); return asset ? asset->GetOrCreateManagedInstance() : nullptr; } /// /// Sets the asset. /// /// The object ID. Uses Scripting to find the registered asset of the given ID. FORCE_INLINE void Set(const Guid& id) { OnSet(id); } /// /// Sets the asset. /// /// The asset. FORCE_INLINE void Set(T* asset) { OnSet(asset); } }; template uint32 GetHash(const SoftAssetReference& key) { return GetHash(key.GetID()); }