// 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());
}