Hierarchy imgui debugger, first take
Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>monroegm-disable-blank-issue-2
parent
3d1ec83f78
commit
77c23b6c8f
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MultiplayerDebugHierarchyReporter.h"
|
||||||
|
|
||||||
|
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||||
|
#include <AzFramework/Visibility/IVisibilitySystem.h>
|
||||||
|
#include <Multiplayer/Components/NetBindComponent.h>
|
||||||
|
#include <Multiplayer/Components/NetworkHierarchyChildComponent.h>
|
||||||
|
|
||||||
|
#if defined(IMGUI_ENABLED)
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
|
||||||
|
namespace Multiplayer
|
||||||
|
{
|
||||||
|
MultiplayerDebugHierarchyReporter::MultiplayerDebugHierarchyReporter()
|
||||||
|
: m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateHierarchyDebug"))
|
||||||
|
{
|
||||||
|
CollectHierarchyRoots();
|
||||||
|
|
||||||
|
AZ::EntitySystemBus::Handler::BusConnect();
|
||||||
|
m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiplayerDebugHierarchyReporter::~MultiplayerDebugHierarchyReporter()
|
||||||
|
{
|
||||||
|
AZ::EntitySystemBus::Handler::BusDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
void MultiplayerDebugHierarchyReporter::OnImGuiUpdate()
|
||||||
|
{
|
||||||
|
#if defined(IMGUI_ENABLED)
|
||||||
|
for (const auto& root : m_hierarchyRoots)
|
||||||
|
{
|
||||||
|
if (const auto* rootComponent = root.second.m_rootComponent)
|
||||||
|
{
|
||||||
|
if (rootComponent->IsHierarchicalRoot())
|
||||||
|
{
|
||||||
|
const AZStd::vector<AZ::Entity*>& hierarchicalChildren = rootComponent->GetHierarchicalEntities();
|
||||||
|
|
||||||
|
if (ImGui::TreeNode(rootComponent->GetEntity()->GetName().c_str(),
|
||||||
|
"Hierarchy, Root entity name [%s]: %4zu members",
|
||||||
|
rootComponent->GetEntity()->GetName().c_str(),
|
||||||
|
hierarchicalChildren.size()))
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Columns(4, "hierarchy_columns");
|
||||||
|
ImGui::Text("EntityId");
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::Text("NetEntityId");
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::Text("Entity Name");
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::Text("Role");
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Columns(4, "hierarchy child info");
|
||||||
|
|
||||||
|
bool firstEntity = true;
|
||||||
|
for (const AZ::Entity* entity : hierarchicalChildren)
|
||||||
|
{
|
||||||
|
ImGui::Text("%s", entity->GetId().ToString().c_str());
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::Text("%u", GetMultiplayer()->GetNetworkEntityManager()->GetNetEntityIdById(entity->GetId()));
|
||||||
|
ImGui::NextColumn();
|
||||||
|
ImGui::Text("%s", entity->GetName().c_str());
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
if (firstEntity)
|
||||||
|
{
|
||||||
|
ImGui::Text("Root node");
|
||||||
|
}
|
||||||
|
else if (entity->FindComponent<NetworkHierarchyRootComponent>())
|
||||||
|
{
|
||||||
|
ImGui::Text("Inner root node");
|
||||||
|
}
|
||||||
|
else if (entity->FindComponent<NetworkHierarchyChildComponent>())
|
||||||
|
{
|
||||||
|
ImGui::Text("Child node");
|
||||||
|
}
|
||||||
|
ImGui::NextColumn();
|
||||||
|
|
||||||
|
firstEntity = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Columns(1);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MultiplayerDebugHierarchyReporter::UpdateDebugOverlay()
|
||||||
|
{
|
||||||
|
if (!m_hierarchyRoots.empty())
|
||||||
|
{
|
||||||
|
if (m_debugDisplay == nullptr)
|
||||||
|
{
|
||||||
|
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
|
||||||
|
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId);
|
||||||
|
m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AZ::u32 stateBefore = m_debugDisplay->GetState();
|
||||||
|
m_debugDisplay->SetColor(AZ::Colors::White);
|
||||||
|
|
||||||
|
for (const auto& root : m_hierarchyRoots)
|
||||||
|
{
|
||||||
|
if (const auto* rootComponent = root.second.m_rootComponent)
|
||||||
|
{
|
||||||
|
if (rootComponent->IsHierarchicalRoot())
|
||||||
|
{
|
||||||
|
const AZStd::vector<AZ::Entity*>& hierarchicalChildren = rootComponent->GetHierarchicalEntities();
|
||||||
|
|
||||||
|
azsprintf(m_statusBuffer, "Hierarchy [%s] %u members", rootComponent->GetEntity()->GetName().c_str(),
|
||||||
|
aznumeric_cast<AZ::u32>(hierarchicalChildren.size()));
|
||||||
|
|
||||||
|
AZ::Vector3 entityPosition = rootComponent->GetEntity()->GetTransform()->GetWorldTranslation();
|
||||||
|
constexpr bool centerText = true;
|
||||||
|
m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_debugDisplay->SetState(stateBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerDebugHierarchyReporter::OnEntityActivated(const AZ::EntityId& entityId)
|
||||||
|
{
|
||||||
|
if (const AZ::Entity* childEntity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId))
|
||||||
|
{
|
||||||
|
if (auto* rootComponent = childEntity->FindComponent<NetworkHierarchyRootComponent>())
|
||||||
|
{
|
||||||
|
HierarchyRootInfo info;
|
||||||
|
info.m_rootComponent = rootComponent;
|
||||||
|
rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent);
|
||||||
|
rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent);
|
||||||
|
|
||||||
|
m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerDebugHierarchyReporter::OnEntityDeactivated(const AZ::EntityId& entityId)
|
||||||
|
{
|
||||||
|
if (const AZ::Entity* childEntity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(entityId))
|
||||||
|
{
|
||||||
|
if (auto* rootComponent = childEntity->FindComponent<NetworkHierarchyRootComponent>())
|
||||||
|
{
|
||||||
|
m_hierarchyRoots.erase(rootComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiplayerDebugHierarchyReporter::CollectHierarchyRoots()
|
||||||
|
{
|
||||||
|
AZStd::vector<AzFramework::VisibilityEntry*> gatheredEntries;
|
||||||
|
const AZ::Sphere awarenessSphere = AZ::Sphere(AZ::Vector3::CreateZero(), 1000.f);
|
||||||
|
AZ::Interface<AzFramework::IVisibilitySystem>::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData)
|
||||||
|
{
|
||||||
|
gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size());
|
||||||
|
for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries)
|
||||||
|
{
|
||||||
|
if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity)
|
||||||
|
{
|
||||||
|
gatheredEntries.push_back(visEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const AzFramework::VisibilityEntry* entry : gatheredEntries)
|
||||||
|
{
|
||||||
|
const AZ::Entity* entity = static_cast<AZ::Entity*>(entry->m_userData);
|
||||||
|
if (auto* rootComponent = entity->FindComponent<NetworkHierarchyRootComponent>())
|
||||||
|
{
|
||||||
|
HierarchyRootInfo info;
|
||||||
|
info.m_rootComponent = rootComponent;
|
||||||
|
rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent);
|
||||||
|
rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent);
|
||||||
|
|
||||||
|
m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AzCore/Component/EntityBus.h>
|
||||||
|
#include <AzCore/EBus/ScheduledEvent.h>
|
||||||
|
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||||
|
#include <Multiplayer/Components/NetworkHierarchyRootComponent.h>
|
||||||
|
|
||||||
|
namespace Multiplayer
|
||||||
|
{
|
||||||
|
class MultiplayerDebugHierarchyReporter
|
||||||
|
: public AZ::EntitySystemBus::Handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MultiplayerDebugHierarchyReporter();
|
||||||
|
~MultiplayerDebugHierarchyReporter() override;
|
||||||
|
|
||||||
|
//! main update loop
|
||||||
|
void OnImGuiUpdate();
|
||||||
|
|
||||||
|
//! Draws bandwidth text over entities
|
||||||
|
void UpdateDebugOverlay();
|
||||||
|
|
||||||
|
//! EntitySystemBus overrides.
|
||||||
|
void OnEntityActivated(const AZ::EntityId& entityId) override;
|
||||||
|
void OnEntityDeactivated(const AZ::EntityId& entityId) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AZ::ScheduledEvent m_updateDebugOverlay;
|
||||||
|
|
||||||
|
AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr;
|
||||||
|
|
||||||
|
struct HierarchyRootInfo
|
||||||
|
{
|
||||||
|
NetworkHierarchyRootComponent* m_rootComponent = nullptr;
|
||||||
|
NetworkHierarchyChangedEvent::Handler m_changedEvent;
|
||||||
|
NetworkHierarchyLeaveEvent::Handler m_leaveEvent;
|
||||||
|
};
|
||||||
|
|
||||||
|
AZStd::unordered_map<NetworkHierarchyRootComponent*, HierarchyRootInfo> m_hierarchyRoots;
|
||||||
|
void CollectHierarchyRoots();
|
||||||
|
|
||||||
|
char m_statusBuffer[100] = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue