Add connections view

This commit is contained in:
Luke Street 2021-05-26 12:23:44 -04:00
parent 4f48a442de
commit 7e9408868f
3 changed files with 280 additions and 21 deletions

View File

@ -10,7 +10,7 @@
namespace metaforce { namespace metaforce {
static std::set<TUniqueId> inspectingEntities; std::set<TUniqueId> ImGuiConsole::inspectingEntities;
static std::unordered_map<CAssetId, std::unique_ptr<CDummyWorld>> dummyWorlds; static std::unordered_map<CAssetId, std::unique_ptr<CDummyWorld>> dummyWorlds;
static std::unordered_map<CAssetId, TCachedToken<CStringTable>> stringTables; static std::unordered_map<CAssetId, TCachedToken<CStringTable>> stringTables;
@ -120,7 +120,7 @@ static void ShowMenuGame() {
} }
} }
static void ImGuiStringViewText(std::string_view text) { void ImGuiStringViewText(std::string_view text) {
ImGui::TextUnformatted(text.begin(), text.end()); ImGui::TextUnformatted(text.begin(), text.end());
} }
@ -138,6 +138,15 @@ static void LerpActorColor(CActor* act) {
static void ShowInspectWindow(bool* isOpen) { static void ShowInspectWindow(bool* isOpen) {
if (ImGui::Begin("Inspect", isOpen)) { if (ImGui::Begin("Inspect", isOpen)) {
CObjectList& list = *g_StateManager->GetObjectList();
ImGui::Text("Objects: %d / 1024", list.size());
if (ImGui::Button("Deselect all")) {
for (const auto& item : list) {
if (TCastToPtr<CActor> act = item) {
act->m_debugSelected = false;
}
}
}
if (ImGui::BeginTable("Entities", 4, if (ImGui::BeginTable("Entities", 4,
ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_RowBg |
ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ScrollY)) { ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ScrollY)) {
@ -150,7 +159,6 @@ static void ShowInspectWindow(bool* isOpen) {
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
CObjectList& list = *g_StateManager->GetObjectList();
std::vector<CEntity*> items; std::vector<CEntity*> items;
items.reserve(list.size()); items.reserve(list.size());
for (auto* ent : list) { for (auto* ent : list) {
@ -185,10 +193,8 @@ static void ShowInspectWindow(bool* isOpen) {
if (ImGui::TableNextColumn()) { if (ImGui::TableNextColumn()) {
auto text = fmt::format(FMT_STRING("{:x}"), uid.Value()); auto text = fmt::format(FMT_STRING("{:x}"), uid.Value());
if (TCastToPtr<CActor> act = item) { if (TCastToPtr<CActor> act = item) {
ImGui::Selectable(text.c_str(), &act->m_debugSelected, ImGuiSelectableFlags_SpanAllColumns); ImGui::Selectable(text.c_str(), &act->m_debugSelected,
if (act->m_debugSelected) { ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap);
LerpActorColor(act);
}
} else { } else {
ImGui::TextUnformatted(text.c_str()); ImGui::TextUnformatted(text.c_str());
} }
@ -201,7 +207,7 @@ static void ShowInspectWindow(bool* isOpen) {
} }
if (ImGui::TableNextColumn()) { if (ImGui::TableNextColumn()) {
if (ImGui::SmallButton("View")) { if (ImGui::SmallButton("View")) {
inspectingEntities.insert(uid); ImGuiConsole::inspectingEntities.insert(uid);
} }
} }
ImGui::PopID(); ImGui::PopID();
@ -220,16 +226,18 @@ static bool showEntityInfoWindow(TUniqueId uid) {
} }
auto name = fmt::format(FMT_STRING("{}##{:x}"), !ent->GetName().empty() ? ent->GetName() : "Entity", uid.Value()); auto name = fmt::format(FMT_STRING("{}##{:x}"), !ent->GetName().empty() ? ent->GetName() : "Entity", uid.Value());
if (ImGui::Begin(name.c_str(), &open, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::Begin(name.c_str(), &open, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::PushID(ent->GetUniqueId().Value());
ent->ImGuiInspect(); ent->ImGuiInspect();
ImGui::PopID();
} }
ImGui::End(); ImGui::End();
return open; return open;
} }
static void ShowAppMainMenuBar() {
static bool showInspectWindow = false; static bool showInspectWindow = false;
static bool showDemoWindow = false; static bool showDemoWindow = false;
bool canInspect = g_StateManager != nullptr && g_StateManager->GetObjectList();
static void ShowAppMainMenuBar(bool canInspect) {
if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("Game")) { if (ImGui::BeginMenu("Game")) {
ShowMenuGame(); ShowMenuGame();
@ -244,6 +252,15 @@ static void ShowAppMainMenuBar() {
} }
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
}
void ImGuiConsole::proc() {
if (stepFrame) {
g_Main->SetPaused(true);
stepFrame = false;
}
bool canInspect = g_StateManager != nullptr && g_StateManager->GetObjectList();
ShowAppMainMenuBar(canInspect);
if (canInspect) { if (canInspect) {
if (showInspectWindow) { if (showInspectWindow) {
ShowInspectWindow(&showInspectWindow); ShowInspectWindow(&showInspectWindow);
@ -256,6 +273,13 @@ static void ShowAppMainMenuBar() {
iter++; iter++;
} }
} }
for (const auto& item : *g_StateManager->GetObjectList()) {
if (TCastToPtr<CActor> act = item) {
if (act->m_debugSelected) {
LerpActorColor(act);
}
}
}
} else { } else {
inspectingEntities.clear(); inspectingEntities.clear();
} }
@ -264,14 +288,6 @@ static void ShowAppMainMenuBar() {
} }
} }
void ImGuiConsole::proc() {
if (stepFrame) {
g_Main->SetPaused(true);
stepFrame = false;
}
ShowAppMainMenuBar();
}
ImGuiConsole::~ImGuiConsole() { ImGuiConsole::~ImGuiConsole() {
dummyWorlds.clear(); dummyWorlds.clear();
stringTables.clear(); stringTables.clear();

View File

@ -1,8 +1,17 @@
#pragma once #pragma once
#include <set>
#include <string_view>
#include "RetroTypes.hpp"
namespace metaforce { namespace metaforce {
void ImGuiStringViewText(std::string_view text);
class ImGuiConsole { class ImGuiConsole {
public: public:
static std::set<TUniqueId> inspectingEntities;
~ImGuiConsole(); ~ImGuiConsole();
void proc(); void proc();
}; };

View File

@ -153,6 +153,10 @@
#include "Runtime/MP1/World/CTryclops.hpp" #include "Runtime/MP1/World/CTryclops.hpp"
#include "Runtime/MP1/World/CWarWasp.hpp" #include "Runtime/MP1/World/CWarWasp.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "ImGuiConsole.hpp"
#include "imgui.h" #include "imgui.h"
#define IMGUI_ENTITY_INSPECT(CLS, PARENT, NAME, BLOCK) \ #define IMGUI_ENTITY_INSPECT(CLS, PARENT, NAME, BLOCK) \
@ -172,9 +176,237 @@
} }
namespace metaforce { namespace metaforce {
static std::string_view FromScriptObjectState(EScriptObjectState state) {
switch (state) {
case EScriptObjectState::Any:
return "Any"sv;
case EScriptObjectState::Active:
return "Active"sv;
case EScriptObjectState::Arrived:
return "Arrived"sv;
case EScriptObjectState::Closed:
return "Closed"sv;
case EScriptObjectState::Entered:
return "Entered"sv;
case EScriptObjectState::Exited:
return "Exited"sv;
case EScriptObjectState::Inactive:
return "Inactive"sv;
case EScriptObjectState::Inside:
return "Inside"sv;
case EScriptObjectState::MaxReached:
return "MaxReached"sv;
case EScriptObjectState::Open:
return "Open"sv;
case EScriptObjectState::Zero:
return "Zero"sv;
case EScriptObjectState::Attack:
return "Attack"sv;
case EScriptObjectState::CloseIn:
return "CloseIn"sv;
case EScriptObjectState::Retreat:
return "Retreat"sv;
case EScriptObjectState::Patrol:
return "Patrol"sv;
case EScriptObjectState::Dead:
return "Dead"sv;
case EScriptObjectState::CameraPath:
return "CameraPath"sv;
case EScriptObjectState::CameraTarget:
return "CameraTarget"sv;
case EScriptObjectState::DeactivateState:
return "DeactivateState"sv;
case EScriptObjectState::Play:
return "Play"sv;
case EScriptObjectState::MassiveDeath:
return "MassiveDeath"sv;
case EScriptObjectState::DeathRattle:
return "DeathRattle"sv;
case EScriptObjectState::AboutToMassivelyDie:
return "AboutToMassivelyDie"sv;
case EScriptObjectState::Damage:
return "Damage"sv;
case EScriptObjectState::InvulnDamage:
return "InvulnDamage"sv;
case EScriptObjectState::MassiveFrozenDeath:
return "MassiveFrozenDeath"sv;
case EScriptObjectState::Modify:
return "Modify"sv;
case EScriptObjectState::ScanStart:
return "ScanStart"sv;
case EScriptObjectState::ScanProcessing:
return "ScanProcessing"sv;
case EScriptObjectState::ScanDone:
return "ScanDone"sv;
case EScriptObjectState::UnFrozen:
return "Unfrozen"sv;
case EScriptObjectState::Default:
return "Default"sv;
case EScriptObjectState::ReflectedDamage:
return "ReflectedDamage"sv;
case EScriptObjectState::InheritBounds:
return "InheritBounds"sv;
}
}
static std::string_view FromScriptObjectMessage(EScriptObjectMessage msg) {
switch (msg) {
case EScriptObjectMessage::None:
return "None"sv;
case EScriptObjectMessage::UNKM0:
return "UNKM0"sv;
case EScriptObjectMessage::Activate:
return "Activate"sv;
case EScriptObjectMessage::Arrived:
return "Arrived"sv;
case EScriptObjectMessage::Close:
return "Close"sv;
case EScriptObjectMessage::Deactivate:
return "Deactivate"sv;
case EScriptObjectMessage::Decrement:
return "Decrement"sv;
case EScriptObjectMessage::Follow:
return "Follow"sv;
case EScriptObjectMessage::Increment:
return "Increment"sv;
case EScriptObjectMessage::Next:
return "Next"sv;
case EScriptObjectMessage::Open:
return "Open"sv;
case EScriptObjectMessage::Reset:
return "Reset"sv;
case EScriptObjectMessage::ResetAndStart:
return "ResetAndStart"sv;
case EScriptObjectMessage::SetToMax:
return "SetToMax"sv;
case EScriptObjectMessage::SetToZero:
return "SetToZero"sv;
case EScriptObjectMessage::Start:
return "Start"sv;
case EScriptObjectMessage::Stop:
return "Stop"sv;
case EScriptObjectMessage::StopAndReset:
return "StopAndReset"sv;
case EScriptObjectMessage::ToggleActive:
return "ToggleActive"sv;
case EScriptObjectMessage::UNKM18:
return "UNKM18"sv;
case EScriptObjectMessage::Action:
return "Action"sv;
case EScriptObjectMessage::Play:
return "Play"sv;
case EScriptObjectMessage::Alert:
return "Alert"sv;
case EScriptObjectMessage::InternalMessage00:
return "InernalMessage00"sv;
case EScriptObjectMessage::OnFloor:
return "OnFloor"sv;
case EScriptObjectMessage::InternalMessage02:
return "InternalMessage02"sv;
case EScriptObjectMessage::InternalMessage03:
return "InternalMessage03"sv;
case EScriptObjectMessage::Falling:
return "Falling"sv;
case EScriptObjectMessage::OnIceSurface:
return "OnIceSurface"sv;
case EScriptObjectMessage::OnMudSlowSurface:
return "OnMudSlowSurface"sv;
case EScriptObjectMessage::OnNormalSurface:
return "OnNormalSurface"sv;
case EScriptObjectMessage::Touched:
return "Touched"sv;
case EScriptObjectMessage::AddPlatformRider:
return "AddPlatformRider"sv;
case EScriptObjectMessage::LandOnNotFloor:
return "LandOnNotFloor"sv;
case EScriptObjectMessage::Registered:
return "Registered"sv;
case EScriptObjectMessage::Deleted:
return "Deleted"sv;
case EScriptObjectMessage::InitializedInArea:
return "InitializedInArea"sv;
case EScriptObjectMessage::WorldInitialized:
return "WorldInitialized"sv;
case EScriptObjectMessage::AddSplashInhabitant:
return "AddSplashInhabitant"sv;
case EScriptObjectMessage::UpdateSplashInhabitant:
return "UpdateSplashInhabitant"sv;
case EScriptObjectMessage::RemoveSplashInhabitant:
return "RemoveSplashInhabitant"sv;
case EScriptObjectMessage::Jumped:
return "Jumped"sv;
case EScriptObjectMessage::Damage:
return "Damage"sv;
case EScriptObjectMessage::InvulnDamage:
return "InvulnDamage"sv;
case EScriptObjectMessage::ProjectileCollide:
return "ProjectileCollide"sv;
case EScriptObjectMessage::InSnakeWeed:
return "InSnakeWeed"sv;
case EScriptObjectMessage::AddPhazonPoolInhabitant:
return "AddPhazonPoolInhabitant"sv;
case EScriptObjectMessage::UpdatePhazonPoolInhabitant:
return "UpdatePhazonPoolInhabitant"sv;
case EScriptObjectMessage::RemovePhazonPoolInhabitant:
return "RemovePhazonPoolInhabitant"sv;
case EScriptObjectMessage::SuspendedMove:
return "SuspendedMove"sv;
}
}
std::string_view CEntity::ImGuiType() { return "Entity"; } std::string_view CEntity::ImGuiType() { return "Entity"; }
void CEntity::ImGuiInspect() { void CEntity::ImGuiInspect() {
if (ImGui::CollapsingHeader("Connections")) {
if (ImGui::BeginTable("Connections", 6,
ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV)) {
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 0, 'id');
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 0, 'type');
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 0, 'name');
ImGui::TableSetupColumn("State", ImGuiTableColumnFlags_WidthFixed, 0, 'stat');
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthFixed, 0, 'msg');
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow();
for (const auto& item : x20_conns) {
const auto uid = g_StateManager->GetIdForScript(item.x8_objId);
CEntity* ent = g_StateManager->ObjectById(uid);
if (ent == nullptr) {
continue;
}
ImGui::PushID(uid.Value());
ImGui::TableNextRow();
if (ImGui::TableNextColumn()) {
auto text = fmt::format(FMT_STRING("{:x}"), uid.Value());
if (TCastToPtr<CActor> act = ent) {
ImGui::Selectable(text.c_str(), &act->m_debugSelected,
ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap);
} else {
ImGui::TextUnformatted(text.c_str());
}
}
if (ImGui::TableNextColumn()) {
ImGuiStringViewText(ent->ImGuiType());
}
if (ImGui::TableNextColumn()) {
ImGuiStringViewText(ent->GetName());
}
if (ImGui::TableNextColumn()) {
ImGuiStringViewText(FromScriptObjectState(item.x0_state));
}
if (ImGui::TableNextColumn()) {
ImGuiStringViewText(FromScriptObjectMessage(item.x4_msg));
}
if (ImGui::TableNextColumn()) {
if (ImGui::SmallButton("View")) {
ImGuiConsole::inspectingEntities.insert(uid);
}
}
ImGui::PopID();
}
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) { if (ImGui::CollapsingHeader("Entity", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Text("ID: %x", x8_uid.Value()); ImGui::Text("ID: %x", x8_uid.Value());
ImGui::Text("Name: %s", x10_name.c_str()); ImGui::Text("Name: %s", x10_name.c_str());
@ -186,6 +418,7 @@ void CEntity::ImGuiInspect() {
IMGUI_ENTITY_INSPECT(CActor, CEntity, Actor, { IMGUI_ENTITY_INSPECT(CActor, CEntity, Actor, {
const zeus::CVector3f& pos = GetTranslation(); const zeus::CVector3f& pos = GetTranslation();
ImGui::Text("Position: %f, %f, %f", pos.x(), pos.y(), pos.z()); ImGui::Text("Position: %f, %f, %f", pos.x(), pos.y(), pos.z());
ImGui::Checkbox("Highlight", &m_debugSelected);
}) })
IMGUI_ENTITY_INSPECT(MP1::CFireFlea::CDeathCameraEffect, CEntity, FireFleaDeathCameraEffect, {}) IMGUI_ENTITY_INSPECT(MP1::CFireFlea::CDeathCameraEffect, CEntity, FireFleaDeathCameraEffect, {})
IMGUI_ENTITY_INSPECT(MP1::CMetroidPrimeRelay, CEntity, MetroidPrimeRelay, {}) IMGUI_ENTITY_INSPECT(MP1::CMetroidPrimeRelay, CEntity, MetroidPrimeRelay, {})
@ -326,7 +559,8 @@ IMGUI_ENTITY_INSPECT(MP1::CRipperControlledPlatform, CScriptPlatform, RipperCont
// <- CAi // <- CAi
IMGUI_ENTITY_INSPECT(CDestroyableRock, CAi, DestroyableRock, {}) IMGUI_ENTITY_INSPECT(CDestroyableRock, CAi, DestroyableRock, {})
IMGUI_ENTITY_INSPECT(CPatterned, CAi, Patterned, {}) IMGUI_ENTITY_INSPECT(CPatterned, CAi, Patterned,
{ BITFIELD_CHECKBOX("Enable state machine", x403_25_enableStateMachine); })
// <- CPatterned // <- CPatterned
IMGUI_ENTITY_INSPECT(MP1::CAtomicAlpha, CPatterned, AtomicAlpha, {}) IMGUI_ENTITY_INSPECT(MP1::CAtomicAlpha, CPatterned, AtomicAlpha, {})