// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Content/Asset.h"
///
/// Asset reference utility that doesn't add reference to that asset. Handles asset unload event.
///
API_CLASS(InBuild) class WeakAssetReferenceBase
{
public:
typedef Delegate<> EventType;
protected:
Asset* _asset;
public:
///
/// The asset unloading event (should cleanup refs to it).
///
EventType Unload;
public:
///
/// Initializes a new instance of the class.
///
WeakAssetReferenceBase()
: _asset(nullptr)
{
}
///
/// Finalizes an instance of the class.
///
~WeakAssetReferenceBase()
{
if (_asset)
{
_asset->OnUnloaded.Unbind(this);
_asset = nullptr;
}
}
public:
///
/// Gets the asset ID or Guid::Empty if not set.
///
/// 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).
///
/// Mono managed object
FORCE_INLINE MonoObject* GetManagedInstance() const
{
return _asset ? _asset->GetOrCreateManagedInstance() : nullptr;
}
///
/// Clears the asset reference.
///
FORCE_INLINE void Unlink()
{
OnSet(nullptr);
}
///
/// Gets the asset property value as string.
///
/// The string.
String ToString() const
{
static String NullStr = TEXT("");
return _asset ? _asset->ToString() : NullStr;
}
protected:
void OnSet(Asset* asset)
{
auto e = _asset;
if (e != asset)
{
if (e)
e->OnUnloaded.Unbind(this);
_asset = e = asset;
if (e)
e->OnUnloaded.Bind(this);
}
}
void OnAssetUnloaded(Asset* asset)
{
ASSERT(_asset == asset);
Unload();
Unlink();
}
};
///
/// Asset reference utility that doesn't add reference to that asset. Handles asset unload event.
///
template
API_CLASS(InBuild) class WeakAssetReference : public WeakAssetReferenceBase
{
public:
///
/// Initializes a new instance of the class.
///
WeakAssetReference()
: WeakAssetReferenceBase()
{
}
///
/// Initializes a new instance of the class.
///
/// The asset to set.
WeakAssetReference(T* asset)
: WeakAssetReferenceBase()
{
OnSet(asset);
}
///
/// Initializes a new instance of the class.
///
/// The other.
WeakAssetReference(const WeakAssetReference& other)
{
OnSet(other.Get());
}
///
/// Finalizes an instance of the class.
///
~WeakAssetReference()
{
}
public:
FORCE_INLINE WeakAssetReference& operator=(const WeakAssetReference& other)
{
OnSet(other.Get());
return *this;
}
FORCE_INLINE WeakAssetReference& operator=(T* other)
{
OnSet(other);
return *this;
}
FORCE_INLINE WeakAssetReference& operator=(const Guid& id)
{
OnSet((T*)LoadAsset(id, T::TypeInitializer));
return *this;
}
FORCE_INLINE bool operator==(T* other)
{
return _asset == other;
}
FORCE_INLINE bool operator==(const WeakAssetReference& other)
{
return _asset == other._asset;
}
///
/// Implicit conversion to the bool.
///
/// The asset.
FORCE_INLINE operator T*() const
{
return (T*)_asset;
}
///
/// Implicit conversion to the asset.
///
/// True if asset has been set, otherwise false.
FORCE_INLINE operator bool() const
{
return _asset != nullptr;
}
///
/// Implicit conversion to the asset.
///
/// The asset.
FORCE_INLINE T* operator->() const
{
return (T*)_asset;
}
///
/// Gets the asset.
///
/// The asset.
FORCE_INLINE T* Get() const
{
return (T*)_asset;
}
///
/// Gets the asset as a given type (static cast).
///
/// The asset.
template
FORCE_INLINE U* As() const
{
return (U*)_asset;
}
public:
///
/// Sets the asset reference.
///
/// The asset.
void Set(T* asset)
{
OnSet(asset);
}
};