Optimize asset references to support direct registration to reduce Delegate memory allocations and overhead
This commit is contained in:
@@ -73,9 +73,9 @@ void BehaviorService::Dispose()
|
||||
|
||||
Behavior::Behavior(const SpawnParams& params)
|
||||
: Script(params)
|
||||
, Tree(this)
|
||||
{
|
||||
_knowledge.Behavior = this;
|
||||
Tree.Changed.Bind<Behavior, &Behavior::ResetLogic>(this);
|
||||
}
|
||||
|
||||
void Behavior::UpdateAsync()
|
||||
@@ -175,6 +175,19 @@ void Behavior::OnDisable()
|
||||
BehaviorServiceInstance.UpdateList.Remove(this);
|
||||
}
|
||||
|
||||
void Behavior::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
ResetLogic();
|
||||
}
|
||||
|
||||
void Behavior::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void Behavior::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool Behavior::GetNodeDebugRelevancy(const BehaviorTreeNode* node, const Behavior* behavior)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/// <summary>
|
||||
/// Behavior instance script that runs Behavior Tree execution.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="Category(\"Flax Engine\")") class FLAXENGINE_API Behavior : public Script
|
||||
API_CLASS(Attributes="Category(\"Flax Engine\")") class FLAXENGINE_API Behavior : public Script, private IAssetReference
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCRIPTING_TYPE(Behavior);
|
||||
@@ -92,6 +92,11 @@ public:
|
||||
void OnDisable() override;
|
||||
|
||||
private:
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
#if USE_EDITOR
|
||||
// Editor-only utilities to debug nodes state.
|
||||
API_FUNCTION(Internal) static bool GetNodeDebugRelevancy(const BehaviorTreeNode* node, const Behavior* behavior);
|
||||
|
||||
@@ -21,9 +21,8 @@ AudioSource::AudioSource(const SpawnParams& params)
|
||||
, _playOnStart(false)
|
||||
, _startTime(0.0f)
|
||||
, _allowSpatialization(true)
|
||||
, Clip(this)
|
||||
{
|
||||
Clip.Changed.Bind<AudioSource, &AudioSource::OnClipChanged>(this);
|
||||
Clip.Loaded.Bind<AudioSource, &AudioSource::OnClipLoaded>(this);
|
||||
}
|
||||
|
||||
void AudioSource::SetVolume(float value)
|
||||
@@ -264,7 +263,7 @@ void AudioSource::RequestStreamingBuffersUpdate()
|
||||
_needToUpdateStreamingBuffers = true;
|
||||
}
|
||||
|
||||
void AudioSource::OnClipChanged()
|
||||
void AudioSource::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
Stop();
|
||||
|
||||
@@ -276,7 +275,7 @@ void AudioSource::OnClipChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSource::OnClipLoaded()
|
||||
void AudioSource::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (!SourceID)
|
||||
return;
|
||||
@@ -302,6 +301,10 @@ void AudioSource::OnClipLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSource::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
bool AudioSource::UseStreaming() const
|
||||
{
|
||||
if (Clip == nullptr || Clip->WaitForLoaded())
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/// Whether or not an audio source is spatial is controlled by the assigned AudioClip.The volume and the pitch of a spatial audio source is controlled by its position and the AudioListener's position/direction/velocity.
|
||||
/// </remarks>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")")
|
||||
class FLAXENGINE_API AudioSource : public Actor
|
||||
class FLAXENGINE_API AudioSource : public Actor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(AudioSource);
|
||||
friend class AudioStreamingHandler;
|
||||
@@ -293,8 +293,10 @@ public:
|
||||
void RequestStreamingBuffersUpdate();
|
||||
|
||||
private:
|
||||
void OnClipChanged();
|
||||
void OnClipLoaded();
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
/// <summary>
|
||||
/// Plays the audio source. Should have buffer(s) binded before.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/LogContext.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||
#include "Engine/Threading/MainThreadTask.h"
|
||||
#include "Engine/Threading/ThreadLocal.h"
|
||||
@@ -34,15 +35,18 @@ bool ContentDeprecated::Clear(bool newValue)
|
||||
|
||||
#endif
|
||||
|
||||
AssetReferenceBase::AssetReferenceBase(IAssetReference* owner)
|
||||
: _owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
AssetReferenceBase::~AssetReferenceBase()
|
||||
{
|
||||
Asset* asset = _asset;
|
||||
if (asset)
|
||||
{
|
||||
_asset = nullptr;
|
||||
asset->OnLoaded.Unbind<AssetReferenceBase, &AssetReferenceBase::OnLoaded>(this);
|
||||
asset->OnUnloaded.Unbind<AssetReferenceBase, &AssetReferenceBase::OnUnloaded>(this);
|
||||
asset->RemoveReference();
|
||||
asset->RemoveReference(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,52 +55,60 @@ String AssetReferenceBase::ToString() const
|
||||
return _asset ? _asset->ToString() : TEXT("<null>");
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
if (_owner)
|
||||
_owner->OnAssetChanged(asset, this);
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Loaded();
|
||||
if (_owner)
|
||||
_owner->OnAssetLoaded(asset, this);
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Unload();
|
||||
OnSet(nullptr);
|
||||
if (_owner)
|
||||
_owner->OnAssetUnloaded(asset, this);
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnSet(Asset* asset)
|
||||
{
|
||||
auto e = _asset;
|
||||
if (e != asset)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
e->OnLoaded.Unbind<AssetReferenceBase, &AssetReferenceBase::OnLoaded>(this);
|
||||
e->OnUnloaded.Unbind<AssetReferenceBase, &AssetReferenceBase::OnUnloaded>(this);
|
||||
e->RemoveReference();
|
||||
}
|
||||
e->RemoveReference(this);
|
||||
_asset = e = asset;
|
||||
if (e)
|
||||
{
|
||||
e->AddReference();
|
||||
e->OnLoaded.Bind<AssetReferenceBase, &AssetReferenceBase::OnLoaded>(this);
|
||||
e->OnUnloaded.Bind<AssetReferenceBase, &AssetReferenceBase::OnUnloaded>(this);
|
||||
}
|
||||
e->AddReference(this);
|
||||
Changed();
|
||||
if (_owner)
|
||||
_owner->OnAssetChanged(asset, this);
|
||||
if (e && e->IsLoaded())
|
||||
{
|
||||
Loaded();
|
||||
if (_owner)
|
||||
_owner->OnAssetLoaded(asset, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnLoaded(Asset* asset)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Loaded();
|
||||
}
|
||||
|
||||
void AssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Unload();
|
||||
OnSet(nullptr);
|
||||
}
|
||||
|
||||
WeakAssetReferenceBase::~WeakAssetReferenceBase()
|
||||
{
|
||||
Asset* asset = _asset;
|
||||
if (asset)
|
||||
{
|
||||
_asset = nullptr;
|
||||
asset->OnUnloaded.Unbind<WeakAssetReferenceBase, &WeakAssetReferenceBase::OnUnloaded>(this);
|
||||
asset->RemoveReference(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,36 +117,43 @@ String WeakAssetReferenceBase::ToString() const
|
||||
return _asset ? _asset->ToString() : TEXT("<null>");
|
||||
}
|
||||
|
||||
void WeakAssetReferenceBase::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void WeakAssetReferenceBase::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void WeakAssetReferenceBase::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Unload();
|
||||
asset->RemoveReference(this, true);
|
||||
_asset = nullptr;
|
||||
}
|
||||
|
||||
void WeakAssetReferenceBase::OnSet(Asset* asset)
|
||||
{
|
||||
auto e = _asset;
|
||||
if (e != asset)
|
||||
{
|
||||
if (e)
|
||||
e->OnUnloaded.Unbind<WeakAssetReferenceBase, &WeakAssetReferenceBase::OnUnloaded>(this);
|
||||
e->RemoveReference(this, true);
|
||||
_asset = e = asset;
|
||||
if (e)
|
||||
e->OnUnloaded.Bind<WeakAssetReferenceBase, &WeakAssetReferenceBase::OnUnloaded>(this);
|
||||
e->AddReference(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
void WeakAssetReferenceBase::OnUnloaded(Asset* asset)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
Unload();
|
||||
asset->OnUnloaded.Unbind<WeakAssetReferenceBase, &WeakAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset = nullptr;
|
||||
}
|
||||
|
||||
SoftAssetReferenceBase::~SoftAssetReferenceBase()
|
||||
{
|
||||
Asset* asset = _asset;
|
||||
if (asset)
|
||||
{
|
||||
_asset = nullptr;
|
||||
asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
asset->RemoveReference();
|
||||
asset->RemoveReference(this);
|
||||
}
|
||||
#if !BUILD_RELEASE
|
||||
_id = Guid::Empty;
|
||||
@@ -146,22 +165,34 @@ String SoftAssetReferenceBase::ToString() const
|
||||
return _asset ? _asset->ToString() : (_id.IsValid() ? _id.ToString() : TEXT("<null>"));
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
_asset->RemoveReference(this);
|
||||
_asset = nullptr;
|
||||
_id = Guid::Empty;
|
||||
Changed();
|
||||
}
|
||||
|
||||
void SoftAssetReferenceBase::OnSet(Asset* asset)
|
||||
{
|
||||
if (_asset == asset)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset->RemoveReference(this);
|
||||
_asset = asset;
|
||||
_id = asset ? asset->GetID() : Guid::Empty;
|
||||
if (asset)
|
||||
{
|
||||
asset->AddReference();
|
||||
asset->OnUnloaded.Bind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
}
|
||||
asset->AddReference(this);
|
||||
Changed();
|
||||
}
|
||||
|
||||
@@ -170,10 +201,7 @@ void SoftAssetReferenceBase::OnSet(const Guid& id)
|
||||
if (_id == id)
|
||||
return;
|
||||
if (_asset)
|
||||
{
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset->RemoveReference();
|
||||
}
|
||||
_asset->RemoveReference(this);
|
||||
_asset = nullptr;
|
||||
_id = id;
|
||||
Changed();
|
||||
@@ -184,21 +212,7 @@ 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)
|
||||
{
|
||||
if (_asset != asset)
|
||||
return;
|
||||
_asset->RemoveReference();
|
||||
_asset->OnUnloaded.Unbind<SoftAssetReferenceBase, &SoftAssetReferenceBase::OnUnloaded>(this);
|
||||
_asset = nullptr;
|
||||
_id = Guid::Empty;
|
||||
Changed();
|
||||
_asset->AddReference(this);
|
||||
}
|
||||
|
||||
Asset::Asset(const SpawnParams& params, const AssetInfo* info)
|
||||
@@ -216,6 +230,41 @@ int32 Asset::GetReferencesCount() const
|
||||
return (int32)Platform::AtomicRead(const_cast<int64 volatile*>(&_refCount));
|
||||
}
|
||||
|
||||
void Asset::AddReference()
|
||||
{
|
||||
Platform::InterlockedIncrement(&_refCount);
|
||||
}
|
||||
|
||||
void Asset::AddReference(IAssetReference* ref, bool week)
|
||||
{
|
||||
if (!week)
|
||||
Platform::InterlockedIncrement(&_refCount);
|
||||
if (ref)
|
||||
{
|
||||
//PROFILE_MEM(EngineDelegate); // Include references tracking memory within Delegate memory
|
||||
Locker.Lock();
|
||||
_references.Add(ref);
|
||||
Locker.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::RemoveReference()
|
||||
{
|
||||
Platform::InterlockedDecrement(&_refCount);
|
||||
}
|
||||
|
||||
void Asset::RemoveReference(IAssetReference* ref, bool week)
|
||||
{
|
||||
if (ref)
|
||||
{
|
||||
Locker.Lock();
|
||||
_references.Remove(ref);
|
||||
Locker.Unlock();
|
||||
}
|
||||
if (!week)
|
||||
Platform::InterlockedDecrement(&_refCount);
|
||||
}
|
||||
|
||||
String Asset::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("{0}, {1}, {2}"), GetTypeName(), GetID(), GetPath());
|
||||
@@ -354,6 +403,7 @@ uint64 Asset::GetMemoryUsage() const
|
||||
if (Platform::AtomicRead(&_loadingTask))
|
||||
result += sizeof(ContentLoadTask);
|
||||
result += (OnLoaded.Capacity() + OnReloading.Capacity() + OnUnloaded.Capacity()) * sizeof(EventType::FunctionType);
|
||||
result += _references.Capacity() * sizeof(HashSet<IAssetReference*>::Bucket);
|
||||
Locker.Unlock();
|
||||
return result;
|
||||
}
|
||||
@@ -628,6 +678,8 @@ void Asset::onLoaded_MainThread()
|
||||
ASSERT(IsInMainThread());
|
||||
|
||||
// Send event
|
||||
for (const auto& e : _references)
|
||||
e.Item->OnAssetLoaded(this, this);
|
||||
OnLoaded(this);
|
||||
}
|
||||
|
||||
@@ -641,6 +693,8 @@ void Asset::onUnload_MainThread()
|
||||
CancelStreaming();
|
||||
|
||||
// Send event
|
||||
for (const auto& e : _references)
|
||||
e.Item->OnAssetUnloaded(this, this);
|
||||
OnUnloaded(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,18 @@
|
||||
public: \
|
||||
explicit type(const SpawnParams& params, const AssetInfo* info)
|
||||
|
||||
// Utility interface for objects that reference asset and want to get notified about asset reference changes.
|
||||
class FLAXENGINE_API IAssetReference
|
||||
{
|
||||
public:
|
||||
// Asset reference got changed.
|
||||
virtual void OnAssetChanged(Asset* asset, void* caller) = 0;
|
||||
// Asset got loaded.
|
||||
virtual void OnAssetLoaded(Asset* asset, void* caller) = 0;
|
||||
// Asset gets unloaded.
|
||||
virtual void OnAssetUnloaded(Asset* asset, void* caller) = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Asset objects base class.
|
||||
/// </summary>
|
||||
@@ -48,6 +60,8 @@ protected:
|
||||
int8 _deleteFileOnUnload : 1; // Indicates that asset source file should be removed on asset unload
|
||||
int8 _isVirtual : 1; // Indicates that asset is pure virtual (generated or temporary, has no storage so won't be saved)
|
||||
|
||||
HashSet<IAssetReference*> _references;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Asset"/> class.
|
||||
@@ -88,18 +102,22 @@ public:
|
||||
/// <summary>
|
||||
/// Adds reference to that asset.
|
||||
/// </summary>
|
||||
FORCE_INLINE void AddReference()
|
||||
{
|
||||
Platform::InterlockedIncrement(&_refCount);
|
||||
}
|
||||
void AddReference();
|
||||
|
||||
/// <summary>
|
||||
/// Adds reference to that asset.
|
||||
/// </summary>
|
||||
void AddReference(IAssetReference* ref, bool week = false);
|
||||
|
||||
/// <summary>
|
||||
/// Removes reference from that asset.
|
||||
/// </summary>
|
||||
FORCE_INLINE void RemoveReference()
|
||||
{
|
||||
Platform::InterlockedDecrement(&_refCount);
|
||||
}
|
||||
void RemoveReference();
|
||||
|
||||
/// <summary>
|
||||
/// Removes reference from that asset.
|
||||
/// </summary>
|
||||
void RemoveReference(IAssetReference* ref, bool week = false);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
/// <summary>
|
||||
/// Asset reference utility. Keeps reference to the linked asset object and handles load/unload events.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API AssetReferenceBase
|
||||
class FLAXENGINE_API AssetReferenceBase : public IAssetReference
|
||||
{
|
||||
protected:
|
||||
Asset* _asset = nullptr;
|
||||
IAssetReference* _owner = nullptr;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
@@ -36,6 +37,12 @@ public:
|
||||
/// </summary>
|
||||
AssetReferenceBase() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="owner">The reference owner to keep notified about asset changes.</param>
|
||||
AssetReferenceBase(IAssetReference* owner);
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="AssetReferenceBase"/> class.
|
||||
/// </summary>
|
||||
@@ -63,10 +70,14 @@ public:
|
||||
/// </summary>
|
||||
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);
|
||||
void OnLoaded(Asset* asset);
|
||||
void OnUnloaded(Asset* asset);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -87,6 +98,13 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReference"/> class.
|
||||
/// </summary>
|
||||
explicit AssetReference(decltype(__nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReference"/> class.
|
||||
/// </summary>
|
||||
@@ -96,6 +114,15 @@ public:
|
||||
OnSet((Asset*)asset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReference"/> class.
|
||||
/// </summary>
|
||||
/// <param name="owner">The reference owner to keep notified about asset changes.</param>
|
||||
explicit AssetReference(IAssetReference* owner)
|
||||
: AssetReferenceBase(owner)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReference"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -19,6 +19,15 @@ API_STRUCT(NoDefault, Template, MarshalAs=JsonAsset*) struct JsonAssetReference
|
||||
OnSet(asset);
|
||||
}
|
||||
|
||||
explicit JsonAssetReference(decltype(__nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
explicit JsonAssetReference(IAssetReference* owner)
|
||||
: AssetReference<JsonAsset>(owner)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the deserialized native object instance of the given type. Returns null if asset is not loaded or loaded object has different type.
|
||||
/// </summary>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/// <summary>
|
||||
/// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API SoftAssetReferenceBase
|
||||
class FLAXENGINE_API SoftAssetReferenceBase : public IAssetReference
|
||||
{
|
||||
protected:
|
||||
Asset* _asset = nullptr;
|
||||
@@ -46,11 +46,16 @@ public:
|
||||
/// </summary>
|
||||
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);
|
||||
void OnSet(const Guid& id);
|
||||
void OnResolve(const ScriptingTypeHandle& type);
|
||||
void OnUnloaded(Asset* asset);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -71,6 +76,13 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
explicit SoftAssetReference(decltype(__nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SoftAssetReference"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/// <summary>
|
||||
/// Asset reference utility that doesn't add reference to that asset. Handles asset unload event.
|
||||
/// </summary>
|
||||
API_CLASS(InBuild) class WeakAssetReferenceBase
|
||||
API_CLASS(InBuild) class WeakAssetReferenceBase : public IAssetReference
|
||||
{
|
||||
public:
|
||||
typedef Delegate<> EventType;
|
||||
@@ -56,9 +56,14 @@ public:
|
||||
/// </summary>
|
||||
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);
|
||||
void OnUnloaded(Asset* asset);
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -72,7 +77,13 @@ public:
|
||||
/// Initializes a new instance of the <see cref="WeakAssetReference"/> class.
|
||||
/// </summary>
|
||||
WeakAssetReference()
|
||||
: WeakAssetReferenceBase()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WeakAssetReference"/> class.
|
||||
/// </summary>
|
||||
explicit WeakAssetReference(decltype(__nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +92,6 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="asset">The asset to set.</param>
|
||||
WeakAssetReference(T* asset)
|
||||
: WeakAssetReferenceBase()
|
||||
{
|
||||
OnSet(asset);
|
||||
}
|
||||
|
||||
@@ -27,16 +27,13 @@ AnimatedModel::AnimatedModel(const SpawnParams& params)
|
||||
, _counter(0)
|
||||
, _lastMinDstSqr(MAX_Real)
|
||||
, _lastUpdateFrame(0)
|
||||
, SkinnedModel(this)
|
||||
, AnimationGraph(this)
|
||||
{
|
||||
_drawCategory = SceneRendering::SceneDrawAsync;
|
||||
GraphInstance.Object = this;
|
||||
_box = BoundingBox(Vector3::Zero);
|
||||
_sphere = BoundingSphere(Vector3::Zero, 0.0f);
|
||||
|
||||
SkinnedModel.Changed.Bind<AnimatedModel, &AnimatedModel::OnSkinnedModelChanged>(this);
|
||||
SkinnedModel.Loaded.Bind<AnimatedModel, &AnimatedModel::OnSkinnedModelLoaded>(this);
|
||||
AnimationGraph.Changed.Bind<AnimatedModel, &AnimatedModel::OnGraphChanged>(this);
|
||||
AnimationGraph.Loaded.Bind<AnimatedModel, &AnimatedModel::OnGraphLoaded>(this);
|
||||
}
|
||||
|
||||
AnimatedModel::~AnimatedModel()
|
||||
@@ -889,6 +886,26 @@ void AnimatedModel::OnGraphLoaded()
|
||||
SyncParameters();
|
||||
}
|
||||
|
||||
void AnimatedModel::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
if (caller == &SkinnedModel)
|
||||
OnSkinnedModelChanged();
|
||||
else if (caller == &AnimationGraph)
|
||||
OnGraphChanged();
|
||||
}
|
||||
|
||||
void AnimatedModel::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
if (caller == &SkinnedModel)
|
||||
OnSkinnedModelLoaded();
|
||||
else if (caller == &AnimationGraph)
|
||||
OnGraphLoaded();
|
||||
}
|
||||
|
||||
void AnimatedModel::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
bool AnimatedModel::HasContentLoaded() const
|
||||
{
|
||||
return (SkinnedModel == nullptr || SkinnedModel->IsLoaded()) && Entries.HasContentLoaded();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/// Performs an animation and renders a skinned model.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Animation/Animated Model\"), ActorToolbox(\"Visuals\")")
|
||||
class FLAXENGINE_API AnimatedModel : public ModelInstanceActor
|
||||
class FLAXENGINE_API AnimatedModel : public ModelInstanceActor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(AnimatedModel);
|
||||
friend class AnimationsSystem;
|
||||
@@ -422,6 +422,11 @@ private:
|
||||
void OnGraphChanged();
|
||||
void OnGraphLoaded();
|
||||
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
public:
|
||||
// [ModelInstanceActor]
|
||||
bool HasContentLoaded() const override;
|
||||
|
||||
@@ -30,7 +30,6 @@ GPU_CB_STRUCT(Data {
|
||||
|
||||
Sky::Sky(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
, _shader(nullptr)
|
||||
, _psSky(nullptr)
|
||||
, _psFog(nullptr)
|
||||
{
|
||||
|
||||
@@ -29,10 +29,9 @@ StaticModel::StaticModel(const SpawnParams& params)
|
||||
, _vertexColorsDirty(false)
|
||||
, _vertexColorsCount(0)
|
||||
, _sortOrder(0)
|
||||
, Model(this)
|
||||
{
|
||||
_drawCategory = SceneRendering::SceneDrawAsync;
|
||||
Model.Changed.Bind<StaticModel, &StaticModel::OnModelChanged>(this);
|
||||
Model.Loaded.Bind<StaticModel, &StaticModel::OnModelLoaded>(this);
|
||||
}
|
||||
|
||||
StaticModel::~StaticModel()
|
||||
@@ -224,7 +223,7 @@ void StaticModel::RemoveVertexColors()
|
||||
_vertexColorsDirty = false;
|
||||
}
|
||||
|
||||
void StaticModel::OnModelChanged()
|
||||
void StaticModel::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
if (_residencyChangedModel)
|
||||
{
|
||||
@@ -241,7 +240,7 @@ void StaticModel::OnModelChanged()
|
||||
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
|
||||
}
|
||||
|
||||
void StaticModel::OnModelLoaded()
|
||||
void StaticModel::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
Entries.SetupIfInvalid(Model);
|
||||
UpdateBounds();
|
||||
@@ -316,6 +315,10 @@ void StaticModel::FlushVertexColors()
|
||||
RenderContext::GPULocker.Unlock();
|
||||
}
|
||||
|
||||
void StaticModel::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
bool StaticModel::HasContentLoaded() const
|
||||
{
|
||||
return (Model == nullptr || Model->IsLoaded()) && Entries.HasContentLoaded();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/// Renders model on the screen.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Model\"), ActorToolbox(\"Visuals\")")
|
||||
class FLAXENGINE_API StaticModel : public ModelInstanceActor
|
||||
class FLAXENGINE_API StaticModel : public ModelInstanceActor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(StaticModel);
|
||||
private:
|
||||
@@ -154,11 +154,14 @@ public:
|
||||
API_FUNCTION() void RemoveVertexColors();
|
||||
|
||||
private:
|
||||
void OnModelChanged();
|
||||
void OnModelLoaded();
|
||||
void OnModelResidencyChanged();
|
||||
void FlushVertexColors();
|
||||
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
public:
|
||||
// [ModelInstanceActor]
|
||||
bool HasContentLoaded() const override;
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
NavMesh::NavMesh(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
, IsDataDirty(false)
|
||||
, DataAsset(this)
|
||||
{
|
||||
DataAsset.Loaded.Bind<NavMesh, &NavMesh::OnDataAssetLoaded>(this);
|
||||
}
|
||||
|
||||
void NavMesh::SaveNavMesh()
|
||||
@@ -100,7 +100,11 @@ void NavMesh::RemoveTiles()
|
||||
navMesh->RemoveTiles(this);
|
||||
}
|
||||
|
||||
void NavMesh::OnDataAssetLoaded()
|
||||
void NavMesh::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void NavMesh::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
// Skip if already has data (prevent reloading navmesh on saving)
|
||||
if (Data.Tiles.HasItems())
|
||||
@@ -126,6 +130,10 @@ void NavMesh::OnDataAssetLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
void NavMesh::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
void NavMesh::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
{
|
||||
// Base
|
||||
|
||||
@@ -15,7 +15,7 @@ class NavMeshRuntime;
|
||||
/// The navigation mesh actor that holds a navigation data for a scene.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Navigation/Nav Mesh\")")
|
||||
class FLAXENGINE_API NavMesh : public Actor
|
||||
class FLAXENGINE_API NavMesh : public Actor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(NavMesh);
|
||||
public:
|
||||
@@ -67,7 +67,11 @@ public:
|
||||
private:
|
||||
void AddTiles();
|
||||
void RemoveTiles();
|
||||
void OnDataAssetLoaded();
|
||||
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
private:
|
||||
bool _navMeshActive = false;
|
||||
|
||||
@@ -16,12 +16,10 @@ ParticleEffect::ParticleEffect(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
, _lastUpdateFrame(0)
|
||||
, _lastMinDstSqr(MAX_Real)
|
||||
, ParticleSystem(this)
|
||||
{
|
||||
_box = BoundingBox(_transform.Translation);
|
||||
BoundingSphere::FromBox(_box, _sphere);
|
||||
|
||||
ParticleSystem.Changed.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemModified>(this);
|
||||
ParticleSystem.Loaded.Bind<ParticleEffect, &ParticleEffect::OnParticleSystemLoaded>(this);
|
||||
}
|
||||
|
||||
void ParticleEffectParameter::Init(ParticleEffect* effect, int32 emitterIndex, int32 paramIndex)
|
||||
@@ -542,18 +540,22 @@ void ParticleEffect::ApplyModifiedParameters()
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleEffect::OnParticleSystemModified()
|
||||
void ParticleEffect::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
Instance.ClearState();
|
||||
_parameters.Resize(0);
|
||||
_parametersVersion = 0;
|
||||
}
|
||||
|
||||
void ParticleEffect::OnParticleSystemLoaded()
|
||||
void ParticleEffect::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
ApplyModifiedParameters();
|
||||
}
|
||||
|
||||
void ParticleEffect::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
}
|
||||
|
||||
bool ParticleEffect::HasContentLoaded() const
|
||||
{
|
||||
if (ParticleSystem == nullptr)
|
||||
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
/// The particle system instance that plays the particles simulation in the game.
|
||||
/// </summary>
|
||||
API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effect\"), ActorToolbox(\"Visuals\")")
|
||||
class FLAXENGINE_API ParticleEffect : public Actor
|
||||
class FLAXENGINE_API ParticleEffect : public Actor, IAssetReference
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(ParticleEffect);
|
||||
public:
|
||||
@@ -388,6 +388,11 @@ private:
|
||||
void OnParticleSystemModified();
|
||||
void OnParticleSystemLoaded();
|
||||
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
|
||||
public:
|
||||
// [Actor]
|
||||
bool HasContentLoaded() const override;
|
||||
|
||||
@@ -20,10 +20,8 @@ Collider::Collider(const SpawnParams& params)
|
||||
, _staticActor(nullptr)
|
||||
, _cachedScale(1.0f)
|
||||
, _contactOffset(2.0f)
|
||||
, Material(this)
|
||||
{
|
||||
Material.Loaded.Bind<Collider, &Collider::OnMaterialChanged>(this);
|
||||
Material.Unload.Bind<Collider, &Collider::OnMaterialChanged>(this);
|
||||
Material.Changed.Bind<Collider, &Collider::OnMaterialChanged>(this);
|
||||
}
|
||||
|
||||
void* Collider::GetPhysicsShape() const
|
||||
@@ -294,13 +292,6 @@ void Collider::DrawPhysicsDebug(RenderView& view)
|
||||
|
||||
#endif
|
||||
|
||||
void Collider::OnMaterialChanged()
|
||||
{
|
||||
// Update the shape material
|
||||
if (_shape)
|
||||
PhysicsBackend::SetShapeMaterial(_shape, Material);
|
||||
}
|
||||
|
||||
void Collider::BeginPlay(SceneBeginData* data)
|
||||
{
|
||||
// Check if has no shape created (it means no rigidbody requested it but also collider may be spawned at runtime)
|
||||
@@ -466,3 +457,20 @@ void Collider::OnPhysicsSceneChanged(PhysicsScene* previous)
|
||||
PhysicsBackend::AddSceneActor(scene, _staticActor);
|
||||
}
|
||||
}
|
||||
|
||||
void Collider::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
// Update the shape material
|
||||
if (_shape && caller == &Material)
|
||||
PhysicsBackend::SetShapeMaterial(_shape, Material);
|
||||
}
|
||||
|
||||
void Collider::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
Collider::OnAssetChanged(asset, caller);
|
||||
}
|
||||
|
||||
void Collider::OnAssetUnloaded(Asset* asset, void* caller)
|
||||
{
|
||||
Collider::OnAssetChanged(asset, caller);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class RigidBody;
|
||||
/// </summary>
|
||||
/// <seealso cref="Actor" />
|
||||
/// <seealso cref="PhysicsColliderActor" />
|
||||
API_CLASS(Abstract) class FLAXENGINE_API Collider : public PhysicsColliderActor
|
||||
API_CLASS(Abstract) class FLAXENGINE_API Collider : public PhysicsColliderActor, protected IAssetReference
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCENE_OBJECT_ABSTRACT(Collider);
|
||||
@@ -154,9 +154,6 @@ protected:
|
||||
/// </summary>
|
||||
void RemoveStaticActor();
|
||||
|
||||
private:
|
||||
void OnMaterialChanged();
|
||||
|
||||
public:
|
||||
// [PhysicsColliderActor]
|
||||
RigidBody* GetAttachedRigidBody() const override;
|
||||
@@ -181,4 +178,9 @@ protected:
|
||||
void OnLayerChanged() override;
|
||||
void OnStaticFlagsChanged() override;
|
||||
void OnPhysicsSceneChanged(PhysicsScene* previous) override;
|
||||
|
||||
// [IAssetReference]
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
void OnAssetUnloaded(Asset* asset, void* caller) override;
|
||||
};
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
|
||||
MeshCollider::MeshCollider(const SpawnParams& params)
|
||||
: Collider(params)
|
||||
, CollisionData(this)
|
||||
{
|
||||
CollisionData.Changed.Bind<MeshCollider, &MeshCollider::OnCollisionDataChanged>(this);
|
||||
CollisionData.Loaded.Bind<MeshCollider, &MeshCollider::OnCollisionDataLoaded>(this);
|
||||
}
|
||||
|
||||
void MeshCollider::OnCollisionDataChanged()
|
||||
@@ -33,8 +32,9 @@ void MeshCollider::OnCollisionDataChanged()
|
||||
|
||||
void MeshCollider::OnCollisionDataLoaded()
|
||||
{
|
||||
UpdateGeometry();
|
||||
UpdateBounds();
|
||||
// Not needed as OnCollisionDataChanged waits for it to be loaded
|
||||
//UpdateGeometry();
|
||||
//UpdateBounds();
|
||||
}
|
||||
|
||||
bool MeshCollider::CanAttach(RigidBody* rigidBody) const
|
||||
@@ -152,3 +152,19 @@ void MeshCollider::GetGeometry(CollisionShape& collision)
|
||||
else
|
||||
collision.SetSphere(minSize);
|
||||
}
|
||||
|
||||
void MeshCollider::OnAssetChanged(Asset* asset, void* caller)
|
||||
{
|
||||
Collider::OnAssetChanged(asset, caller);
|
||||
|
||||
if (caller == &CollisionData)
|
||||
OnCollisionDataChanged();
|
||||
}
|
||||
|
||||
void MeshCollider::OnAssetLoaded(Asset* asset, void* caller)
|
||||
{
|
||||
Collider::OnAssetLoaded(asset, caller);
|
||||
|
||||
if (caller == &CollisionData)
|
||||
OnCollisionDataLoaded();
|
||||
}
|
||||
|
||||
@@ -42,4 +42,6 @@ protected:
|
||||
#endif
|
||||
void UpdateBounds() override;
|
||||
void GetGeometry(CollisionShape& collision) override;
|
||||
void OnAssetChanged(Asset* asset, void* caller) override;
|
||||
void OnAssetLoaded(Asset* asset, void* caller) override;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,6 @@ GPU_CB_STRUCT(Data {
|
||||
ColorGradingPass::ColorGradingPass()
|
||||
: _useVolumeTexture(false)
|
||||
, _lutFormat()
|
||||
, _shader(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#include "Engine/Graphics/Shaders/GPUShader.h"
|
||||
|
||||
ForwardPass::ForwardPass()
|
||||
: _shader(nullptr)
|
||||
, _psApplyDistortion(nullptr)
|
||||
: _psApplyDistortion(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ int32 VolumetricFogGridInjectionGroupSize = 4;
|
||||
int32 VolumetricFogIntegrationGroupSize = 8;
|
||||
|
||||
VolumetricFogPass::VolumetricFogPass()
|
||||
: _shader(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user