diff --git a/Source/Engine/AI/Behavior.cpp b/Source/Engine/AI/Behavior.cpp index 7e647e945..442051d73 100644 --- a/Source/Engine/AI/Behavior.cpp +++ b/Source/Engine/AI/Behavior.cpp @@ -73,9 +73,9 @@ void BehaviorService::Dispose() Behavior::Behavior(const SpawnParams& params) : Script(params) + , Tree(this) { _knowledge.Behavior = this; - Tree.Changed.Bind(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) diff --git a/Source/Engine/AI/Behavior.h b/Source/Engine/AI/Behavior.h index 4919847fa..b1c39ffc6 100644 --- a/Source/Engine/AI/Behavior.h +++ b/Source/Engine/AI/Behavior.h @@ -11,7 +11,7 @@ /// /// Behavior instance script that runs Behavior Tree execution. /// -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); diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index cff89e7e1..2a061ad48 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -21,9 +21,8 @@ AudioSource::AudioSource(const SpawnParams& params) , _playOnStart(false) , _startTime(0.0f) , _allowSpatialization(true) + , Clip(this) { - Clip.Changed.Bind(this); - Clip.Loaded.Bind(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()) diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index b83a2b408..9d6d28ab4 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -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. /// 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; /// /// Plays the audio source. Should have buffer(s) binded before. diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp index fd4fae421..86801b078 100644 --- a/Source/Engine/Content/Asset.cpp +++ b/Source/Engine/Content/Asset.cpp @@ -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(this); - asset->OnUnloaded.Unbind(this); - asset->RemoveReference(); + asset->RemoveReference(this); } } @@ -51,52 +55,60 @@ String AssetReferenceBase::ToString() const return _asset ? _asset->ToString() : TEXT(""); } +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(this); - e->OnUnloaded.Unbind(this); - e->RemoveReference(); - } + e->RemoveReference(this); _asset = e = asset; if (e) - { - e->AddReference(); - e->OnLoaded.Bind(this); - e->OnUnloaded.Bind(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(this); + asset->RemoveReference(this, true); } } @@ -105,36 +117,43 @@ String WeakAssetReferenceBase::ToString() const return _asset ? _asset->ToString() : TEXT(""); } +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(this); + e->RemoveReference(this, true); _asset = e = asset; if (e) - e->OnUnloaded.Bind(this); + e->AddReference(this, true); } } -void WeakAssetReferenceBase::OnUnloaded(Asset* asset) -{ - if (_asset != asset) - return; - Unload(); - asset->OnUnloaded.Unbind(this); - _asset = nullptr; -} - SoftAssetReferenceBase::~SoftAssetReferenceBase() { Asset* asset = _asset; if (asset) { _asset = nullptr; - asset->OnUnloaded.Unbind(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("")); } +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(this); - _asset->RemoveReference(); - } + _asset->RemoveReference(this); _asset = asset; _id = asset ? asset->GetID() : Guid::Empty; if (asset) - { - asset->AddReference(); - asset->OnUnloaded.Bind(this); - } + asset->AddReference(this); Changed(); } @@ -170,10 +201,7 @@ void SoftAssetReferenceBase::OnSet(const Guid& id) if (_id == id) return; if (_asset) - { - _asset->OnUnloaded.Unbind(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(this); - _asset->AddReference(); - } -} - -void SoftAssetReferenceBase::OnUnloaded(Asset* asset) -{ - if (_asset != asset) - return; - _asset->RemoveReference(); - _asset->OnUnloaded.Unbind(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(&_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::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); } diff --git a/Source/Engine/Content/Asset.h b/Source/Engine/Content/Asset.h index c16ea337e..17d8c8b5f 100644 --- a/Source/Engine/Content/Asset.h +++ b/Source/Engine/Content/Asset.h @@ -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; +}; + /// /// Asset objects base class. /// @@ -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 _references; + public: /// /// Initializes a new instance of the class. @@ -88,18 +102,22 @@ public: /// /// Adds reference to that asset. /// - FORCE_INLINE void AddReference() - { - Platform::InterlockedIncrement(&_refCount); - } + void AddReference(); + + /// + /// Adds reference to that asset. + /// + void AddReference(IAssetReference* ref, bool week = false); /// /// Removes reference from that asset. /// - FORCE_INLINE void RemoveReference() - { - Platform::InterlockedDecrement(&_refCount); - } + void RemoveReference(); + + /// + /// Removes reference from that asset. + /// + void RemoveReference(IAssetReference* ref, bool week = false); public: /// diff --git a/Source/Engine/Content/AssetReference.h b/Source/Engine/Content/AssetReference.h index 09e637e57..cd380a39c 100644 --- a/Source/Engine/Content/AssetReference.h +++ b/Source/Engine/Content/AssetReference.h @@ -7,10 +7,11 @@ /// /// Asset reference utility. Keeps reference to the linked asset object and handles load/unload events. /// -class FLAXENGINE_API AssetReferenceBase +class FLAXENGINE_API AssetReferenceBase : public IAssetReference { protected: Asset* _asset = nullptr; + IAssetReference* _owner = nullptr; public: /// @@ -36,6 +37,12 @@ public: /// 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. /// @@ -63,10 +70,14 @@ public: /// 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); }; /// @@ -87,6 +98,13 @@ public: { } + /// + /// Initializes a new instance of the class. + /// + explicit AssetReference(decltype(__nullptr)) + { + } + /// /// Initializes a new instance of the class. /// @@ -96,6 +114,15 @@ public: 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. /// diff --git a/Source/Engine/Content/JsonAssetReference.h b/Source/Engine/Content/JsonAssetReference.h index 7e0ef528a..4325ca79e 100644 --- a/Source/Engine/Content/JsonAssetReference.h +++ b/Source/Engine/Content/JsonAssetReference.h @@ -19,6 +19,15 @@ API_STRUCT(NoDefault, Template, MarshalAs=JsonAsset*) struct JsonAssetReference OnSet(asset); } + explicit JsonAssetReference(decltype(__nullptr)) + { + } + + explicit JsonAssetReference(IAssetReference* owner) + : AssetReference(owner) + { + } + /// /// Gets the deserialized native object instance of the given type. Returns null if asset is not loaded or loaded object has different type. /// diff --git a/Source/Engine/Content/SoftAssetReference.h b/Source/Engine/Content/SoftAssetReference.h index e02fd1a4a..ef9adcde1 100644 --- a/Source/Engine/Content/SoftAssetReference.h +++ b/Source/Engine/Content/SoftAssetReference.h @@ -7,7 +7,7 @@ /// /// The asset soft reference. Asset gets referenced (loaded) on actual use (ID reference is resolving it). /// -class FLAXENGINE_API SoftAssetReferenceBase +class FLAXENGINE_API SoftAssetReferenceBase : public IAssetReference { protected: Asset* _asset = nullptr; @@ -46,11 +46,16 @@ public: /// 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); }; /// @@ -71,6 +76,13 @@ public: { } + /// + /// Initializes a new instance of the class. + /// + explicit SoftAssetReference(decltype(__nullptr)) + { + } + /// /// Initializes a new instance of the class. /// diff --git a/Source/Engine/Content/WeakAssetReference.h b/Source/Engine/Content/WeakAssetReference.h index c6df857d2..d67be0643 100644 --- a/Source/Engine/Content/WeakAssetReference.h +++ b/Source/Engine/Content/WeakAssetReference.h @@ -7,7 +7,7 @@ /// /// Asset reference utility that doesn't add reference to that asset. Handles asset unload event. /// -API_CLASS(InBuild) class WeakAssetReferenceBase +API_CLASS(InBuild) class WeakAssetReferenceBase : public IAssetReference { public: typedef Delegate<> EventType; @@ -56,9 +56,14 @@ public: /// 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); }; /// @@ -72,7 +77,13 @@ public: /// Initializes a new instance of the class. /// WeakAssetReference() - : WeakAssetReferenceBase() + { + } + + /// + /// Initializes a new instance of the class. + /// + explicit WeakAssetReference(decltype(__nullptr)) { } @@ -81,7 +92,6 @@ public: /// /// The asset to set. WeakAssetReference(T* asset) - : WeakAssetReferenceBase() { OnSet(asset); } diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index ee95d6233..c4225ef94 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -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(this); - SkinnedModel.Loaded.Bind(this); - AnimationGraph.Changed.Bind(this); - AnimationGraph.Loaded.Bind(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(); diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h index e13e515d9..6f87ab9cd 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.h +++ b/Source/Engine/Level/Actors/AnimatedModel.h @@ -13,7 +13,7 @@ /// Performs an animation and renders a skinned model. /// 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; diff --git a/Source/Engine/Level/Actors/Sky.cpp b/Source/Engine/Level/Actors/Sky.cpp index 4e635489f..0aa3bf070 100644 --- a/Source/Engine/Level/Actors/Sky.cpp +++ b/Source/Engine/Level/Actors/Sky.cpp @@ -30,7 +30,6 @@ GPU_CB_STRUCT(Data { Sky::Sky(const SpawnParams& params) : Actor(params) - , _shader(nullptr) , _psSky(nullptr) , _psFog(nullptr) { diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index 38c1eed90..912009b3b 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -29,10 +29,9 @@ StaticModel::StaticModel(const SpawnParams& params) , _vertexColorsDirty(false) , _vertexColorsCount(0) , _sortOrder(0) + , Model(this) { _drawCategory = SceneRendering::SceneDrawAsync; - Model.Changed.Bind(this); - Model.Loaded.Bind(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(); diff --git a/Source/Engine/Level/Actors/StaticModel.h b/Source/Engine/Level/Actors/StaticModel.h index 09553f577..e6ed701cc 100644 --- a/Source/Engine/Level/Actors/StaticModel.h +++ b/Source/Engine/Level/Actors/StaticModel.h @@ -11,7 +11,7 @@ /// Renders model on the screen. /// 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; diff --git a/Source/Engine/Navigation/NavMesh.cpp b/Source/Engine/Navigation/NavMesh.cpp index 6479542a1..ee3e48f3e 100644 --- a/Source/Engine/Navigation/NavMesh.cpp +++ b/Source/Engine/Navigation/NavMesh.cpp @@ -17,8 +17,8 @@ NavMesh::NavMesh(const SpawnParams& params) : Actor(params) , IsDataDirty(false) + , DataAsset(this) { - DataAsset.Loaded.Bind(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 diff --git a/Source/Engine/Navigation/NavMesh.h b/Source/Engine/Navigation/NavMesh.h index 40423696d..fcfbd27e2 100644 --- a/Source/Engine/Navigation/NavMesh.h +++ b/Source/Engine/Navigation/NavMesh.h @@ -15,7 +15,7 @@ class NavMeshRuntime; /// The navigation mesh actor that holds a navigation data for a scene. /// 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; diff --git a/Source/Engine/Particles/ParticleEffect.cpp b/Source/Engine/Particles/ParticleEffect.cpp index 1359dbcf2..93ccef55c 100644 --- a/Source/Engine/Particles/ParticleEffect.cpp +++ b/Source/Engine/Particles/ParticleEffect.cpp @@ -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(this); - ParticleSystem.Loaded.Bind(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) diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index 9be31c4c7..8529732dd 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -118,7 +118,7 @@ public: /// The particle system instance that plays the particles simulation in the game. /// 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; diff --git a/Source/Engine/Physics/Colliders/Collider.cpp b/Source/Engine/Physics/Colliders/Collider.cpp index 0ff51e8e6..5ebef0a9f 100644 --- a/Source/Engine/Physics/Colliders/Collider.cpp +++ b/Source/Engine/Physics/Colliders/Collider.cpp @@ -20,10 +20,8 @@ Collider::Collider(const SpawnParams& params) , _staticActor(nullptr) , _cachedScale(1.0f) , _contactOffset(2.0f) + , Material(this) { - Material.Loaded.Bind(this); - Material.Unload.Bind(this); - Material.Changed.Bind(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); +} diff --git a/Source/Engine/Physics/Colliders/Collider.h b/Source/Engine/Physics/Colliders/Collider.h index 835d89a22..17e1d7883 100644 --- a/Source/Engine/Physics/Colliders/Collider.h +++ b/Source/Engine/Physics/Colliders/Collider.h @@ -15,7 +15,7 @@ class RigidBody; /// /// /// -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: /// 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; }; diff --git a/Source/Engine/Physics/Colliders/MeshCollider.cpp b/Source/Engine/Physics/Colliders/MeshCollider.cpp index 0902f1106..e4e6948e3 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.cpp +++ b/Source/Engine/Physics/Colliders/MeshCollider.cpp @@ -11,9 +11,8 @@ MeshCollider::MeshCollider(const SpawnParams& params) : Collider(params) + , CollisionData(this) { - CollisionData.Changed.Bind(this); - CollisionData.Loaded.Bind(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(); +} diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h index e6b1b7a82..89f013552 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.h +++ b/Source/Engine/Physics/Colliders/MeshCollider.h @@ -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; }; diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp index 3b531b30f..43b49f091 100644 --- a/Source/Engine/Renderer/ColorGradingPass.cpp +++ b/Source/Engine/Renderer/ColorGradingPass.cpp @@ -39,7 +39,6 @@ GPU_CB_STRUCT(Data { ColorGradingPass::ColorGradingPass() : _useVolumeTexture(false) , _lutFormat() - , _shader(nullptr) { } diff --git a/Source/Engine/Renderer/ForwardPass.cpp b/Source/Engine/Renderer/ForwardPass.cpp index caf624609..c0d57b498 100644 --- a/Source/Engine/Renderer/ForwardPass.cpp +++ b/Source/Engine/Renderer/ForwardPass.cpp @@ -14,8 +14,7 @@ #include "Engine/Graphics/Shaders/GPUShader.h" ForwardPass::ForwardPass() - : _shader(nullptr) - , _psApplyDistortion(nullptr) + : _psApplyDistortion(nullptr) { } diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 817f25eef..c56812c72 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -19,7 +19,6 @@ int32 VolumetricFogGridInjectionGroupSize = 4; int32 VolumetricFogIntegrationGroupSize = 8; VolumetricFogPass::VolumetricFogPass() - : _shader(nullptr) { }