diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp index 740a87a91..c29db6bee 100644 --- a/Source/Engine/Level/Scene/SceneRendering.cpp +++ b/Source/Engine/Level/Scene/SceneRendering.cpp @@ -10,6 +10,23 @@ #include "Engine/Profiler/ProfilerCPU.h" #endif +ISceneRenderingListener::~ISceneRenderingListener() +{ + for (SceneRendering* scene : _scenes) + { + scene->_listeners.Remove(this); + } +} + +void ISceneRenderingListener::ListenSceneRendering(SceneRendering* scene) +{ + if (!_scenes.Contains(scene)) + { + _scenes.Add(scene); + scene->_listeners.Add(this); + } +} + void SceneRendering::Draw(RenderContext& renderContext) { auto& view = renderContext.View; @@ -73,6 +90,12 @@ void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext) void SceneRendering::Clear() { + for (auto* listener : _listeners) + { + listener->OnSceneRenderingClear(this); + listener->_scenes.Remove(this); + } + _listeners.Clear(); Actors.Clear(); #if USE_EDITOR PhysicsDebug.Clear(); @@ -95,6 +118,8 @@ int32 SceneRendering::AddActor(Actor* a) e.LayerMask = a->GetLayerMask(); e.Bounds = a->GetSphere(); e.NoCulling = a->_drawNoCulling; + for (auto* listener : _listeners) + listener->OnSceneRenderingAddActor(a); return key; } @@ -104,6 +129,8 @@ void SceneRendering::UpdateActor(Actor* a, int32 key) return; auto& e = Actors[key]; ASSERT_LOW_LAYER(a == e.Actor); + for (auto* listener : _listeners) + listener->OnSceneRenderingUpdateActor(a, e.Bounds); e.LayerMask = a->GetLayerMask(); e.Bounds = a->GetSphere(); } @@ -114,6 +141,8 @@ void SceneRendering::RemoveActor(Actor* a, int32& key) { auto& e = Actors[key]; ASSERT_LOW_LAYER(a == e.Actor); + for (auto* listener : _listeners) + listener->OnSceneRenderingRemoveActor(a); e.Actor = nullptr; e.LayerMask = 0; } diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h index afcb078ea..160a89510 100644 --- a/Source/Engine/Level/Scene/SceneRendering.h +++ b/Source/Engine/Level/Scene/SceneRendering.h @@ -8,6 +8,7 @@ #include "Engine/Level/Actor.h" class SceneRenderTask; +class SceneRendering; struct PostProcessSettings; struct RenderContext; struct RenderView; @@ -32,6 +33,28 @@ public: virtual void Blend(PostProcessSettings& other, float weight) = 0; }; +/// +/// Interface for objects to plug into Scene Rendering and listen for its evens such as static actors changes which are relevant for drawing cache. +/// +/// +class FLAXENGINE_API ISceneRenderingListener +{ + friend SceneRendering; +private: + Array> _scenes; +public: + ~ISceneRenderingListener(); + + // Starts listening to the scene rendering events. + void ListenSceneRendering(SceneRendering* scene); + + // Events called by Scene Rendering + virtual void OnSceneRenderingAddActor(Actor* a) = 0; + virtual void OnSceneRenderingUpdateActor(Actor* a, const BoundingSphere& prevBounds) = 0; + virtual void OnSceneRenderingRemoveActor(Actor* a) = 0; + virtual void OnSceneRenderingClear(SceneRendering* scene) = 0; +}; + /// /// Scene rendering helper subsystem that boosts the level rendering by providing efficient objects cache and culling implementation. /// @@ -59,6 +82,10 @@ private: Array ViewportIcons; #endif + // Listener - some rendering systems cache state of the scene (eg. in RenderBuffers::CustomBuffer), this extensions allows those systems to invalidate cache and handle scene changes + friend ISceneRenderingListener; + Array> _listeners; + public: /// /// Draws the scene. Performs the optimized actors culling and draw calls submission for the current render pass (defined by the render view).