Add SoftAssetReference type

This commit is contained in:
Wojtek Figat
2022-02-28 23:15:35 +01:00
parent 6738bc8dea
commit 4a9c746bed
5 changed files with 352 additions and 12 deletions

View File

@@ -2,6 +2,7 @@
#include "Asset.h"
#include "Content.h"
#include "SoftAssetReference.h"
#include "Cache/AssetsCache.h"
#include "Loading/ContentLoadingManager.h"
#include "Loading/Tasks/LoadAssetTask.h"
@@ -102,6 +103,65 @@ void WeakAssetReferenceBase::OnUnloaded(Asset* asset)
_asset = nullptr;
}
String SoftAssetReferenceBase::ToString() const
{
return _asset ? _asset->ToString() : (_id.IsValid() ? _id.ToString() : TEXT("<null>"));
}
void SoftAssetReferenceBase::OnSet(Asset* asset)
{
if (_asset == asset)
return;
if (_asset)
{
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
_asset->RemoveReference();
}
_asset = asset;
_id = asset ? asset->GetID() : Guid::Empty;
if (asset)
{
asset->AddReference();
asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
}
Changed();
}
void SoftAssetReferenceBase::OnSet(const Guid& id)
{
if (_id == id)
return;
if (_asset)
{
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
_asset->RemoveReference();
}
_asset = nullptr;
_id = id;
Changed();
}
void SoftAssetReferenceBase::OnResolve(const ScriptingTypeHandle& type)
{
ASSERT(!_asset);
_asset = ::LoadAsset(_id, type);
if (_asset)
{
_asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
_asset->AddReference();
}
}
void SoftAssetReferenceBase::OnUnloaded(Asset* asset)
{
ASSERT(_asset == asset);
_asset->RemoveReference();
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
_asset = nullptr;
_id = Guid::Empty;
Changed();
}
Asset::Asset(const SpawnParams& params, const AssetInfo* info)
: ManagedScriptingObject(params)
, _refCount(0)

View File

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

View File

@@ -13,6 +13,8 @@
struct Version;
struct VariantType;
template<typename T>
class SoftAssetReference;
// @formatter:off
@@ -513,6 +515,26 @@ namespace Serialization
v = id;
}
// Soft Asset Reference
template<typename T>
inline bool ShouldSerialize(const SoftAssetReference<T>& v, const void* otherObj)
{
return !otherObj || v.Get() != ((SoftAssetReference<T>*)otherObj)->Get();
}
template<typename T>
inline void Serialize(ISerializable::SerializeStream& stream, const SoftAssetReference<T>& v, const void* otherObj)
{
stream.Guid(v.GetID());
}
template<typename T>
inline void Deserialize(ISerializable::DeserializeStream& stream, SoftAssetReference<T>& v, ISerializeModifier* modifier)
{
Guid id;
Deserialize(stream, id, modifier);
v = id;
}
// Array
template<typename T, typename AllocationType = HeapAllocation>