Graphics/GraphicsComponent: Add visibility control
This commit is contained in:
parent
c9aba016a8
commit
d2cfc5fdf5
|
|
@ -21,22 +21,32 @@ namespace Nz
|
||||||
public:
|
public:
|
||||||
struct Renderable;
|
struct Renderable;
|
||||||
|
|
||||||
GraphicsComponent();
|
inline GraphicsComponent(bool initialyVisible = true);
|
||||||
GraphicsComponent(const GraphicsComponent&) = default;
|
GraphicsComponent(const GraphicsComponent&) = default;
|
||||||
GraphicsComponent(GraphicsComponent&&) = default;
|
GraphicsComponent(GraphicsComponent&&) = default;
|
||||||
~GraphicsComponent() = default;
|
~GraphicsComponent() = default;
|
||||||
|
|
||||||
inline void AttachRenderable(std::shared_ptr<InstancedRenderable> renderable, UInt32 renderMask = 0xFFFFFFFF);
|
inline void AttachRenderable(std::shared_ptr<InstancedRenderable> renderable, UInt32 renderMask = 0xFFFFFFFF);
|
||||||
|
|
||||||
|
inline void Clear();
|
||||||
|
|
||||||
inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable);
|
inline void DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable);
|
||||||
|
|
||||||
inline const std::vector<Renderable>& GetRenderables() const;
|
inline const std::vector<Renderable>& GetRenderables() const;
|
||||||
inline const WorldInstancePtr& GetWorldInstance() const;
|
inline const WorldInstancePtr& GetWorldInstance() const;
|
||||||
|
|
||||||
|
inline void Hide();
|
||||||
|
|
||||||
|
inline bool IsVisible() const;
|
||||||
|
|
||||||
|
inline void Show(bool show = true);
|
||||||
|
|
||||||
GraphicsComponent& operator=(const GraphicsComponent&) = default;
|
GraphicsComponent& operator=(const GraphicsComponent&) = default;
|
||||||
GraphicsComponent& operator=(GraphicsComponent&&) = default;
|
GraphicsComponent& operator=(GraphicsComponent&&) = default;
|
||||||
|
|
||||||
NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
|
NazaraSignal(OnRenderableAttached, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
|
||||||
NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
|
NazaraSignal(OnRenderableDetach, GraphicsComponent* /*graphicsComponent*/, const Renderable& /*renderable*/);
|
||||||
|
NazaraSignal(OnVisibilityUpdate, GraphicsComponent* /*graphicsComponent*/, bool /*newVisibilityState*/);
|
||||||
|
|
||||||
struct Renderable
|
struct Renderable
|
||||||
{
|
{
|
||||||
|
|
@ -47,6 +57,7 @@ namespace Nz
|
||||||
private:
|
private:
|
||||||
std::vector<Renderable> m_renderables;
|
std::vector<Renderable> m_renderables;
|
||||||
WorldInstancePtr m_worldInstance;
|
WorldInstancePtr m_worldInstance;
|
||||||
|
bool m_isVisible;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline GraphicsComponent::GraphicsComponent()
|
inline GraphicsComponent::GraphicsComponent(bool initialyVisible) :
|
||||||
|
m_isVisible(initialyVisible)
|
||||||
{
|
{
|
||||||
m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools
|
m_worldInstance = std::make_shared<WorldInstance>(); //< FIXME: Use pools
|
||||||
}
|
}
|
||||||
|
|
@ -21,6 +22,14 @@ namespace Nz
|
||||||
OnRenderableAttached(this, m_renderables.back());
|
OnRenderableAttached(this, m_renderables.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::Clear()
|
||||||
|
{
|
||||||
|
for (const auto& renderable : m_renderables)
|
||||||
|
OnRenderableDetach(this, renderable);
|
||||||
|
|
||||||
|
m_renderables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
inline void GraphicsComponent::DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable)
|
inline void GraphicsComponent::DetachRenderable(const std::shared_ptr<InstancedRenderable>& renderable)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(m_renderables.begin(), m_renderables.end(), [&](const auto& renderableEntry) { return renderableEntry.renderable == renderable; });
|
auto it = std::find_if(m_renderables.begin(), m_renderables.end(), [&](const auto& renderableEntry) { return renderableEntry.renderable == renderable; });
|
||||||
|
|
@ -41,6 +50,25 @@ namespace Nz
|
||||||
{
|
{
|
||||||
return m_worldInstance;
|
return m_worldInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::Hide()
|
||||||
|
{
|
||||||
|
return Show(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool GraphicsComponent::IsVisible() const
|
||||||
|
{
|
||||||
|
return m_isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::Show(bool show)
|
||||||
|
{
|
||||||
|
if (m_isVisible != show)
|
||||||
|
{
|
||||||
|
OnVisibilityUpdate(this, show);
|
||||||
|
m_isVisible = show;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Graphics/DebugOff.hpp>
|
#include <Nazara/Graphics/DebugOff.hpp>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ namespace Nz
|
||||||
void OnGraphicsDestroy(entt::registry& registry, entt::entity entity);
|
void OnGraphicsDestroy(entt::registry& registry, entt::entity entity);
|
||||||
void OnNodeDestroy(entt::registry& registry, entt::entity entity);
|
void OnNodeDestroy(entt::registry& registry, entt::entity entity);
|
||||||
void UpdateInstances(entt::registry& registry);
|
void UpdateInstances(entt::registry& registry);
|
||||||
|
void UpdateVisibility(entt::registry& registry);
|
||||||
|
|
||||||
struct CameraEntity
|
struct CameraEntity
|
||||||
{
|
{
|
||||||
|
|
@ -51,6 +52,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
NazaraSlot(GraphicsComponent, OnRenderableAttached, onRenderableAttached);
|
NazaraSlot(GraphicsComponent, OnRenderableAttached, onRenderableAttached);
|
||||||
NazaraSlot(GraphicsComponent, OnRenderableDetach, onRenderableDetach);
|
NazaraSlot(GraphicsComponent, OnRenderableDetach, onRenderableDetach);
|
||||||
|
NazaraSlot(GraphicsComponent, OnVisibilityUpdate, onVisibilityUpdate);
|
||||||
NazaraSlot(Node, OnNodeInvalidation, onNodeInvalidation);
|
NazaraSlot(Node, OnNodeInvalidation, onNodeInvalidation);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -64,6 +66,8 @@ namespace Nz
|
||||||
std::unique_ptr<FramePipeline> m_pipeline;
|
std::unique_ptr<FramePipeline> m_pipeline;
|
||||||
std::unordered_map<entt::entity, CameraEntity> m_cameraEntities;
|
std::unordered_map<entt::entity, CameraEntity> m_cameraEntities;
|
||||||
std::unordered_map<entt::entity, GraphicsEntity> m_graphicsEntities;
|
std::unordered_map<entt::entity, GraphicsEntity> m_graphicsEntities;
|
||||||
|
std::unordered_set<entt::entity> m_newlyHiddenEntities;
|
||||||
|
std::unordered_set<entt::entity> m_newlyVisibleEntities;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
viewerData.rebuildDepthPrepass = true;
|
viewerData.rebuildDepthPrepass = true;
|
||||||
viewerData.rebuildForwardPass = true;
|
viewerData.rebuildForwardPass = true;
|
||||||
|
viewerData.prepare = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -118,6 +119,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
viewerData.rebuildDepthPrepass = true;
|
viewerData.rebuildDepthPrepass = true;
|
||||||
viewerData.rebuildForwardPass = true;
|
viewerData.rebuildForwardPass = true;
|
||||||
|
viewerData.prepare = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -447,6 +449,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
viewerData.rebuildDepthPrepass = true;
|
viewerData.rebuildDepthPrepass = true;
|
||||||
viewerData.rebuildForwardPass = true;
|
viewerData.rebuildForwardPass = true;
|
||||||
|
viewerData.prepare = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,12 @@ namespace Nz
|
||||||
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
||||||
NodeComponent& entityNode = registry.get<NodeComponent>(entity);
|
NodeComponent& entityNode = registry.get<NodeComponent>(entity);
|
||||||
|
|
||||||
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
if (entityGfx.IsVisible())
|
||||||
for (const auto& renderableEntry : entityGfx.GetRenderables())
|
{
|
||||||
m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
|
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
||||||
|
for (const auto& renderableEntry : entityGfx.GetRenderables())
|
||||||
|
m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
|
||||||
|
}
|
||||||
|
|
||||||
m_invalidatedWorldNode.insert(entity);
|
m_invalidatedWorldNode.insert(entity);
|
||||||
|
|
||||||
|
|
@ -75,17 +78,38 @@ namespace Nz
|
||||||
|
|
||||||
graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
|
graphicsEntity.onRenderableAttached.Connect(entityGfx.OnRenderableAttached, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
|
||||||
{
|
{
|
||||||
|
if (!gfx->IsVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
|
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
|
||||||
m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
|
m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
|
||||||
});
|
});
|
||||||
|
|
||||||
graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
|
graphicsEntity.onRenderableDetach.Connect(entityGfx.OnRenderableDetach, [this](GraphicsComponent* gfx, const GraphicsComponent::Renderable& renderableEntry)
|
||||||
{
|
{
|
||||||
|
if (!gfx->IsVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
|
const WorldInstancePtr& worldInstance = gfx->GetWorldInstance();
|
||||||
m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get());
|
m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
graphicsEntity.onVisibilityUpdate.Connect(entityGfx.OnVisibilityUpdate, [this, entity](GraphicsComponent* /*gfx*/, bool isVisible)
|
||||||
|
{
|
||||||
|
if (isVisible)
|
||||||
|
{
|
||||||
|
m_newlyHiddenEntities.erase(entity);
|
||||||
|
m_newlyVisibleEntities.insert(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_newlyHiddenEntities.insert(entity);
|
||||||
|
m_newlyVisibleEntities.erase(entity);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
UpdateVisibility(registry);
|
||||||
UpdateInstances(registry);
|
UpdateInstances(registry);
|
||||||
|
|
||||||
m_pipeline->Render(renderFrame);
|
m_pipeline->Render(renderFrame);
|
||||||
|
|
@ -104,6 +128,8 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_graphicsEntities.erase(entity);
|
m_graphicsEntities.erase(entity);
|
||||||
m_invalidatedWorldNode.erase(entity);
|
m_invalidatedWorldNode.erase(entity);
|
||||||
|
m_newlyHiddenEntities.erase(entity);
|
||||||
|
m_newlyVisibleEntities.erase(entity);
|
||||||
|
|
||||||
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
||||||
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
||||||
|
|
@ -113,6 +139,9 @@ namespace Nz
|
||||||
|
|
||||||
void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity)
|
void RenderSystem::OnNodeDestroy(entt::registry& registry, entt::entity entity)
|
||||||
{
|
{
|
||||||
|
m_newlyHiddenEntities.erase(entity);
|
||||||
|
m_newlyVisibleEntities.erase(entity);
|
||||||
|
|
||||||
if (registry.try_get<CameraComponent>(entity))
|
if (registry.try_get<CameraComponent>(entity))
|
||||||
OnCameraDestroy(registry, entity);
|
OnCameraDestroy(registry, entity);
|
||||||
|
|
||||||
|
|
@ -146,4 +175,29 @@ namespace Nz
|
||||||
}
|
}
|
||||||
m_invalidatedWorldNode.clear();
|
m_invalidatedWorldNode.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderSystem::UpdateVisibility(entt::registry& registry)
|
||||||
|
{
|
||||||
|
// Unregister drawables for hidden entities
|
||||||
|
for (entt::entity entity : m_newlyHiddenEntities)
|
||||||
|
{
|
||||||
|
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
||||||
|
|
||||||
|
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
||||||
|
for (const auto& renderableEntry : entityGfx.GetRenderables())
|
||||||
|
m_pipeline->UnregisterInstancedDrawable(worldInstance, renderableEntry.renderable.get());
|
||||||
|
}
|
||||||
|
m_newlyHiddenEntities.clear();
|
||||||
|
|
||||||
|
// Register drawables for newly visible entities
|
||||||
|
for (entt::entity entity : m_newlyVisibleEntities)
|
||||||
|
{
|
||||||
|
GraphicsComponent& entityGfx = registry.get<GraphicsComponent>(entity);
|
||||||
|
|
||||||
|
const WorldInstancePtr& worldInstance = entityGfx.GetWorldInstance();
|
||||||
|
for (const auto& renderableEntry : entityGfx.GetRenderables())
|
||||||
|
m_pipeline->RegisterInstancedDrawable(worldInstance, renderableEntry.renderable.get(), renderableEntry.renderMask);
|
||||||
|
}
|
||||||
|
m_newlyVisibleEntities.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue