// Copyright (c) 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 IAssetReference
{
protected:
Asset* _asset = nullptr;
IAssetReference* _owner = nullptr;
public:
///
/// The asset loaded event (fired when asset gets loaded or is already loaded after change).
///
Action Loaded;
///
/// The asset unloading event (should cleanup refs to it).
///
Action Unload;
///
/// Action fired when field gets changed (link a new asset or change to the another value).
///
Action Changed;
public:
NON_COPYABLE(AssetReferenceBase);
///
/// Initializes a new instance of the class.
///
AssetReferenceBase() = default;
///
/// Initializes a new instance of the class.
///
/// The reference owner to keep notified about asset changes.
AssetReferenceBase(IAssetReference* owner);
///
/// 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;
public:
// [IAssetReference]
void OnAssetChanged(Asset* asset, void* caller) override;
void OnAssetLoaded(Asset* asset, void* caller) override;
void OnAssetUnloaded(Asset* asset, void* caller) override;
protected:
void OnSet(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.
///
explicit AssetReference(decltype(__nullptr))
{
}
///
/// Initializes a new instance of the class.
///
/// The asset to set.
AssetReference(T* asset)
{
OnSet((Asset*)asset);
}
///
/// Initializes a new instance of the class.
///
/// The reference owner to keep notified about asset changes.
explicit AssetReference(IAssetReference* owner)
: AssetReferenceBase(owner)
{
}
///
/// Initializes a new instance of the class.
///
/// The other.
AssetReference(const AssetReference& other)
{
OnSet(other._asset);
}
AssetReference(AssetReference&& other) noexcept
{
OnSet(other._asset);
other.OnSet(nullptr);
}
AssetReference& operator=(AssetReference&& other)
{
if (&other != this)
{
OnSet(other._asset);
other.OnSet(nullptr);
}
return *this;
}
///
/// Finalizes an instance of the class.
///
~AssetReference()
{
}
public:
FORCE_INLINE AssetReference& operator=(const AssetReference& other)
{
OnSet(other._asset);
return *this;
}
FORCE_INLINE AssetReference& operator=(T* other)
{
OnSet((Asset*)other);
return *this;
}
FORCE_INLINE AssetReference& operator=(const Guid& id)
{
OnSet(::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*)asset);
}
};
template
uint32 GetHash(const AssetReference& key)
{
return GetHash(key.GetID());
}