mirror of https://github.com/AxioDL/metaforce.git
Improve overall Inspect performance & fixes
This commit is contained in:
parent
33eacc0b07
commit
36fa020a4c
|
@ -27,6 +27,13 @@ static std::wstring_convert<deletable_facet<std::codecvt<char16_t, char, std::mb
|
||||||
|
|
||||||
std::string readUtf8String(CStringTable* tbl, int idx) { return conv16.to_bytes(tbl->GetString(idx)); }
|
std::string readUtf8String(CStringTable* tbl, int idx) { return conv16.to_bytes(tbl->GetString(idx)); }
|
||||||
|
|
||||||
|
static bool containsCaseInsensitive(std::string_view str, std::string_view val) {
|
||||||
|
return std::search(str.begin(), str.end(), val.begin(), val.end(),
|
||||||
|
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }) != str.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiStringViewText(std::string_view text) { ImGui::TextUnformatted(text.begin(), text.end()); }
|
||||||
|
|
||||||
static const std::vector<std::pair<std::string, CAssetId>> ListWorlds() {
|
static const std::vector<std::pair<std::string, CAssetId>> ListWorlds() {
|
||||||
std::vector<std::pair<std::string, CAssetId>> worlds;
|
std::vector<std::pair<std::string, CAssetId>> worlds;
|
||||||
for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) {
|
for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) {
|
||||||
|
@ -90,11 +97,6 @@ static void Warp(const CAssetId worldId, TAreaId aId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool containsCaseInsensitive(std::string_view str, std::string_view val) {
|
|
||||||
return std::search(str.begin(), str.end(), val.begin(), val.end(),
|
|
||||||
[](char ch1, char ch2) { return std::toupper(ch1) == std::toupper(ch2); }) != str.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool stepFrame = false;
|
static bool stepFrame = false;
|
||||||
|
|
||||||
static void ShowMenuGame() {
|
static void ShowMenuGame() {
|
||||||
|
@ -125,9 +127,7 @@ static void ShowMenuGame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiStringViewText(std::string_view text) { ImGui::TextUnformatted(text.begin(), text.end()); }
|
void ImGuiConsole::LerpDebugColor(CActor* act) {
|
||||||
|
|
||||||
static void LerpActorColor(CActor* act) {
|
|
||||||
act->m_debugAddColorTime += 1.f / 60.f;
|
act->m_debugAddColorTime += 1.f / 60.f;
|
||||||
float lerp = act->m_debugAddColorTime;
|
float lerp = act->m_debugAddColorTime;
|
||||||
if (lerp > 2.f) {
|
if (lerp > 2.f) {
|
||||||
|
@ -139,19 +139,100 @@ static void LerpActorColor(CActor* act) {
|
||||||
act->m_debugAddColor = zeus::CColor::lerp(zeus::skClear, zeus::skBlue, lerp);
|
act->m_debugAddColor = zeus::CColor::lerp(zeus::skClear, zeus::skBlue, lerp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowInspectWindow(bool* isOpen) {
|
void ImGuiConsole::UpdateEntityEntries() {
|
||||||
|
CObjectList& list = g_StateManager->GetAllObjectList();
|
||||||
|
s16 uid = list.GetFirstObjectIndex();
|
||||||
|
while (uid != -1) {
|
||||||
|
ImGuiEntityEntry& entry = ImGuiConsole::entities[uid];
|
||||||
|
if (entry.uid == kInvalidUniqueId || entry.ent == nullptr) {
|
||||||
|
CEntity* ent = list.GetObjectByIndex(uid);
|
||||||
|
entry.uid = ent->GetUniqueId();
|
||||||
|
entry.ent = ent;
|
||||||
|
entry.type = ent->ImGuiType();
|
||||||
|
entry.name = ent->GetName();
|
||||||
|
entry.isActor = TCastToPtr<CActor>(ent).IsValid();
|
||||||
|
} else {
|
||||||
|
entry.active = entry.ent->GetActive();
|
||||||
|
}
|
||||||
|
if (entry.isActor && (entry.ent->m_debugSelected || entry.ent->m_debugHovered)) {
|
||||||
|
LerpDebugColor(entry.AsActor());
|
||||||
|
}
|
||||||
|
uid = list.GetNextObjectIndex(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiConsole::BeginEntityRow(const ImGuiEntityEntry& entry) {
|
||||||
|
ImGui::PushID(entry.uid.Value());
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
bool isActive = entry.active;
|
||||||
|
|
||||||
|
ImVec4 textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||||
|
if (!isActive) {
|
||||||
|
textColor.w = 0.5f;
|
||||||
|
}
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, textColor);
|
||||||
|
|
||||||
|
if (ImGui::TableNextColumn()) {
|
||||||
|
auto text = fmt::format(FMT_STRING("{:x}"), entry.uid.Value());
|
||||||
|
ImGui::Selectable(text.c_str(), &entry.ent->m_debugSelected,
|
||||||
|
ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap);
|
||||||
|
entry.ent->m_debugHovered = ImGui::IsItemHovered();
|
||||||
|
|
||||||
|
if (ImGui::BeginPopupContextItem(text.c_str())) {
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
if (ImGui::MenuItem(isActive ? "Deactivate" : "Activate")) {
|
||||||
|
entry.ent->SetActive(!isActive);
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Highlight", nullptr, &entry.ent->m_debugSelected)) {
|
||||||
|
entry.ent->SetActive(!isActive);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{0.77f, 0.12f, 0.23f, 1.f});
|
||||||
|
if (ImGui::MenuItem("Delete")) {
|
||||||
|
g_StateManager->FreeScriptObject(entry.uid);
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::EndPopup();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, textColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiConsole::EndEntityRow(const ImGuiEntityEntry& entry) {
|
||||||
|
if (ImGui::TableNextColumn()) {
|
||||||
|
if (ImGui::SmallButton("View")) {
|
||||||
|
ImGuiConsole::inspectingEntities.insert(entry.uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RenderEntityColumns(const ImGuiEntityEntry& entry) {
|
||||||
|
ImGuiConsole::BeginEntityRow(entry);
|
||||||
|
if (ImGui::TableNextColumn()) {
|
||||||
|
ImGuiStringViewText(entry.type);
|
||||||
|
}
|
||||||
|
if (ImGui::TableNextColumn()) {
|
||||||
|
ImGuiStringViewText(entry.name);
|
||||||
|
}
|
||||||
|
ImGuiConsole::EndEntityRow(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiConsole::ShowInspectWindow(bool* isOpen) {
|
||||||
|
static bool activeOnly = false;
|
||||||
static std::array<char, 40> filterText{};
|
static std::array<char, 40> filterText{};
|
||||||
if (ImGui::Begin("Inspect", isOpen)) {
|
if (ImGui::Begin("Inspect", isOpen)) {
|
||||||
CObjectList& list = *g_StateManager->GetObjectList();
|
CObjectList& list = g_StateManager->GetAllObjectList();
|
||||||
ImGui::Text("Objects: %d / 1024", list.size());
|
ImGui::Text("Objects: %d / 1024", list.size());
|
||||||
if (ImGui::Button("Deselect all")) {
|
if (ImGui::Button("Deselect all")) {
|
||||||
for (const auto ent : list) {
|
for (auto* const ent : list) {
|
||||||
if (TCastToPtr<CActor> act = ent) {
|
ent->m_debugSelected = false;
|
||||||
act->m_debugSelected = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::InputText("Filter", filterText.data(), filterText.size());
|
ImGui::InputText("Filter", filterText.data(), filterText.size());
|
||||||
|
ImGui::Checkbox("Active", &activeOnly);
|
||||||
|
|
||||||
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)) {
|
||||||
|
@ -164,104 +245,78 @@ 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();
|
||||||
std::vector<CEntity*> items;
|
|
||||||
items.reserve(list.size());
|
ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs();
|
||||||
for (auto* ent : list) {
|
bool hasSortSpec = sortSpecs != nullptr &&
|
||||||
std::string_view search{filterText.data(), strlen(filterText.data())};
|
sortSpecs->SpecsCount == 1 && // no multi-sort
|
||||||
if (!search.empty()) {
|
// We can skip sorting if we just want uid ascending,
|
||||||
std::string_view type = ent->ImGuiType();
|
// since that's how we iterate over CObjectList
|
||||||
std::string_view name = ent->GetName();
|
(sortSpecs->Specs[0].ColumnUserID != 'id' ||
|
||||||
if (!containsCaseInsensitive(type, search) && !containsCaseInsensitive(name, search)) {
|
sortSpecs->Specs[0].SortDirection != ImGuiSortDirection_Ascending);
|
||||||
|
std::string_view search{filterText.data(), strlen(filterText.data())};
|
||||||
|
if (!search.empty() || activeOnly || hasSortSpec) {
|
||||||
|
std::vector<s16> sortedList;
|
||||||
|
sortedList.reserve(list.size());
|
||||||
|
s16 uid = list.GetFirstObjectIndex();
|
||||||
|
while (uid != -1) {
|
||||||
|
ImGuiEntityEntry& entry = ImGuiConsole::entities[uid];
|
||||||
|
if (activeOnly && !entry.active) {
|
||||||
|
uid = list.GetNextObjectIndex(uid);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!search.empty() && !containsCaseInsensitive(entry.type, search) &&
|
||||||
|
!containsCaseInsensitive(entry.name, search)) {
|
||||||
|
uid = list.GetNextObjectIndex(uid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sortedList.push_back(uid);
|
||||||
|
uid = list.GetNextObjectIndex(uid);
|
||||||
}
|
}
|
||||||
items.push_back(ent);
|
if (hasSortSpec) {
|
||||||
}
|
const auto& spec = sortSpecs->Specs[0];
|
||||||
if (ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs()) {
|
if (spec.ColumnUserID == 'id') {
|
||||||
for (int i = 0; i < sortSpecs->SpecsCount; ++i) {
|
if (spec.SortDirection == ImGuiSortDirection_Ascending) {
|
||||||
const auto& specs = sortSpecs->Specs[i];
|
// no-op
|
||||||
if (specs.ColumnUserID == 'id') {
|
} else {
|
||||||
std::sort(items.begin(), items.end(), [&](CEntity* a, CEntity* b) {
|
std::sort(sortedList.begin(), sortedList.end(), [&](s16 a, s16 b) { return a < b; });
|
||||||
u16 aId = a->GetUniqueId().Value();
|
}
|
||||||
u16 bId = b->GetUniqueId().Value();
|
} else if (spec.ColumnUserID == 'name') {
|
||||||
return specs.SortDirection == ImGuiSortDirection_Ascending ? aId < bId : aId > bId;
|
std::sort(sortedList.begin(), sortedList.end(), [&](s16 a, s16 b) {
|
||||||
|
int compare = ImGuiConsole::entities[a].name.compare(ImGuiConsole::entities[b].name);
|
||||||
|
return spec.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
|
||||||
});
|
});
|
||||||
} else if (specs.ColumnUserID == 'name') {
|
} else if (spec.ColumnUserID == 'type') {
|
||||||
std::sort(items.begin(), items.end(), [&](CEntity* a, CEntity* b) {
|
std::sort(sortedList.begin(), sortedList.end(), [&](s16 a, s16 b) {
|
||||||
int compare = a->GetName().compare(b->GetName());
|
int compare = ImGuiConsole::entities[a].type.compare(ImGuiConsole::entities[b].type);
|
||||||
return specs.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
|
return spec.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
|
||||||
});
|
|
||||||
} else if (specs.ColumnUserID == 'type') {
|
|
||||||
std::sort(items.begin(), items.end(), [&](CEntity* a, CEntity* b) {
|
|
||||||
int compare = a->ImGuiType().compare(b->ImGuiType());
|
|
||||||
return specs.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto& item : sortedList) {
|
||||||
|
RenderEntityColumns(ImGuiConsole::entities[item]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Render uid ascending
|
||||||
|
s16 uid = list.GetFirstObjectIndex();
|
||||||
|
while (uid != -1) {
|
||||||
|
RenderEntityColumns(ImGuiConsole::entities[uid]);
|
||||||
|
uid = list.GetNextObjectIndex(uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const auto ent : items) {
|
|
||||||
TUniqueId uid = ent->GetUniqueId();
|
|
||||||
ImGui::PushID(uid.Value());
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
bool isActive = ent->GetActive();
|
|
||||||
if (!isActive) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, 0xAAFFFFFF);
|
|
||||||
}
|
|
||||||
if (ImGui::TableNextColumn()) {
|
|
||||||
auto text = fmt::format(FMT_STRING("{:x}"), uid.Value());
|
|
||||||
bool tmp = false;
|
|
||||||
bool* selected = &tmp;
|
|
||||||
TCastToPtr<CActor> act = ent;
|
|
||||||
if (act != nullptr) {
|
|
||||||
selected = &act->m_debugSelected;
|
|
||||||
}
|
|
||||||
ImGui::Selectable(text.c_str(), selected,
|
|
||||||
ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap);
|
|
||||||
if (ImGui::BeginPopupContextItem(text.c_str())) {
|
|
||||||
if (!isActive) {
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem(isActive ? "Deactivate" : "Activate")) {
|
|
||||||
ent->SetActive(!isActive);
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
if (!isActive) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, 0xAAFFFFFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ImGui::TableNextColumn()) {
|
|
||||||
ImGuiStringViewText(ent->ImGuiType());
|
|
||||||
}
|
|
||||||
if (ImGui::TableNextColumn()) {
|
|
||||||
ImGuiStringViewText(ent->GetName());
|
|
||||||
}
|
|
||||||
if (ImGui::TableNextColumn()) {
|
|
||||||
if (ImGui::SmallButton("View")) {
|
|
||||||
ImGuiConsole::inspectingEntities.insert(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isActive) {
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool showEntityInfoWindow(TUniqueId uid) {
|
bool ImGuiConsole::ShowEntityInfoWindow(TUniqueId uid) {
|
||||||
bool open = true;
|
bool open = true;
|
||||||
CEntity* ent = g_StateManager->ObjectById(uid);
|
ImGuiEntityEntry& entry = ImGuiConsole::entities[uid.Value()];
|
||||||
if (ent == nullptr) {
|
auto name = fmt::format(FMT_STRING("{}##{:x}"), !entry.name.empty() ? entry.name : "Entity", uid.Value());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
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());
|
ImGui::PushID(uid.Value());
|
||||||
ent->ImGuiInspect();
|
entry.ent->ImGuiInspect();
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
@ -271,7 +326,9 @@ static bool showEntityInfoWindow(TUniqueId uid) {
|
||||||
static bool showInspectWindow = false;
|
static bool showInspectWindow = false;
|
||||||
static bool showDemoWindow = false;
|
static bool showDemoWindow = false;
|
||||||
|
|
||||||
static void ShowAppMainMenuBar(bool canInspect) {
|
std::array<ImGuiEntityEntry, 1024> ImGuiConsole::entities;
|
||||||
|
|
||||||
|
void ImGuiConsole::ShowAppMainMenuBar(bool canInspect) {
|
||||||
if (ImGui::BeginMainMenuBar()) {
|
if (ImGui::BeginMainMenuBar()) {
|
||||||
if (ImGui::BeginMenu("Game")) {
|
if (ImGui::BeginMenu("Game")) {
|
||||||
ShowMenuGame();
|
ShowMenuGame();
|
||||||
|
@ -288,40 +345,55 @@ static void ShowAppMainMenuBar(bool canInspect) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiConsole::proc() {
|
void ImGuiConsole::PreUpdate() {
|
||||||
if (stepFrame) {
|
if (stepFrame) {
|
||||||
g_Main->SetPaused(true);
|
g_Main->SetPaused(true);
|
||||||
stepFrame = false;
|
stepFrame = false;
|
||||||
}
|
}
|
||||||
bool canInspect = g_StateManager != nullptr && g_StateManager->GetObjectList();
|
bool canInspect = g_StateManager != nullptr && g_StateManager->GetObjectList();
|
||||||
ShowAppMainMenuBar(canInspect);
|
ShowAppMainMenuBar(canInspect);
|
||||||
if (canInspect) {
|
if (canInspect && (showInspectWindow || !inspectingEntities.empty())) {
|
||||||
|
UpdateEntityEntries();
|
||||||
if (showInspectWindow) {
|
if (showInspectWindow) {
|
||||||
ShowInspectWindow(&showInspectWindow);
|
ShowInspectWindow(&showInspectWindow);
|
||||||
}
|
}
|
||||||
auto iter = inspectingEntities.begin();
|
auto iter = inspectingEntities.begin();
|
||||||
while (iter != inspectingEntities.end()) {
|
while (iter != inspectingEntities.end()) {
|
||||||
if (!showEntityInfoWindow(*iter)) {
|
if (!ShowEntityInfoWindow(*iter)) {
|
||||||
iter = inspectingEntities.erase(iter);
|
iter = inspectingEntities.erase(iter);
|
||||||
} else {
|
} else {
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto ent : *g_StateManager->GetObjectList()) {
|
|
||||||
if (TCastToPtr<CActor> act = ent) {
|
|
||||||
if (act->m_debugSelected) {
|
|
||||||
LerpActorColor(act);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
inspectingEntities.clear();
|
|
||||||
}
|
}
|
||||||
if (showDemoWindow) {
|
if (showDemoWindow) {
|
||||||
ImGui::ShowDemoWindow(&showDemoWindow);
|
ImGui::ShowDemoWindow(&showDemoWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGuiConsole::PostUpdate() {
|
||||||
|
if (g_StateManager != nullptr && g_StateManager->GetObjectList()) {
|
||||||
|
// Clear deleted objects
|
||||||
|
CObjectList& list = g_StateManager->GetAllObjectList();
|
||||||
|
for (s16 uid = 0; uid < s16(entities.size()); uid++) {
|
||||||
|
ImGuiEntityEntry& item = entities[uid];
|
||||||
|
if (item.uid == kInvalidUniqueId) {
|
||||||
|
continue; // already cleared
|
||||||
|
}
|
||||||
|
CEntity* ent = list.GetObjectByIndex(uid);
|
||||||
|
if (ent == nullptr || ent != item.ent) {
|
||||||
|
// Remove inspect windows for deleted entities
|
||||||
|
inspectingEntities.erase(item.uid);
|
||||||
|
item.uid = kInvalidUniqueId;
|
||||||
|
item.ent = nullptr; // for safety
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entities.fill(ImGuiEntityEntry{});
|
||||||
|
inspectingEntities.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiConsole::~ImGuiConsole() {
|
ImGuiConsole::~ImGuiConsole() {
|
||||||
dummyWorlds.clear();
|
dummyWorlds.clear();
|
||||||
stringTables.clear();
|
stringTables.clear();
|
||||||
|
|
|
@ -4,15 +4,49 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "RetroTypes.hpp"
|
#include "RetroTypes.hpp"
|
||||||
|
#include "Runtime/World/CEntity.hpp"
|
||||||
|
#include "Runtime/World/CActor.hpp"
|
||||||
|
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
void ImGuiStringViewText(std::string_view text);
|
void ImGuiStringViewText(std::string_view text);
|
||||||
|
|
||||||
|
struct ImGuiEntityEntry {
|
||||||
|
TUniqueId uid = kInvalidUniqueId;
|
||||||
|
CEntity* ent = nullptr;
|
||||||
|
std::string_view type;
|
||||||
|
std::string_view name;
|
||||||
|
bool active = false;
|
||||||
|
bool isActor = false;
|
||||||
|
|
||||||
|
ImGuiEntityEntry() {}
|
||||||
|
ImGuiEntityEntry(TUniqueId uid, CEntity* ent, std::string_view type, std::string_view name, bool active)
|
||||||
|
: uid(uid), ent(ent), type(type), name(name), active(active) {}
|
||||||
|
|
||||||
|
CActor* AsActor() const {
|
||||||
|
if (isActor) {
|
||||||
|
return static_cast<CActor*>(ent);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ImGuiConsole {
|
class ImGuiConsole {
|
||||||
public:
|
public:
|
||||||
static std::set<TUniqueId> inspectingEntities;
|
static std::set<TUniqueId> inspectingEntities;
|
||||||
|
static std::array<ImGuiEntityEntry, 1024> entities;
|
||||||
|
|
||||||
~ImGuiConsole();
|
~ImGuiConsole();
|
||||||
void proc();
|
void PreUpdate();
|
||||||
|
void PostUpdate();
|
||||||
|
|
||||||
|
static void BeginEntityRow(const ImGuiEntityEntry& entry);
|
||||||
|
static void EndEntityRow(const ImGuiEntityEntry& entry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void ShowAppMainMenuBar(bool canInspect);
|
||||||
|
static bool ShowEntityInfoWindow(TUniqueId uid);
|
||||||
|
static void ShowInspectWindow(bool* isOpen);
|
||||||
|
static void LerpDebugColor(CActor* act);
|
||||||
|
static void UpdateEntityEntries();
|
||||||
};
|
};
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -201,26 +201,19 @@ void CEntity::ImGuiInspect() {
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
for (const auto& item : x20_conns) {
|
for (const auto& item : x20_conns) {
|
||||||
const auto uid = g_StateManager->GetIdForScript(item.x8_objId);
|
const auto uid = g_StateManager->GetIdForScript(item.x8_objId);
|
||||||
CEntity* ent = g_StateManager->ObjectById(uid);
|
if (uid == kInvalidUniqueId) {
|
||||||
if (ent == nullptr) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ImGui::PushID(uid.Value());
|
ImGuiEntityEntry& entry = ImGuiConsole::entities[uid.Value()];
|
||||||
ImGui::TableNextRow();
|
if (entry.uid == kInvalidUniqueId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ImGuiConsole::BeginEntityRow(entry);
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
auto text = fmt::format(FMT_STRING("{:x}"), uid.Value());
|
ImGuiStringViewText(entry.type);
|
||||||
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()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText(ent->ImGuiType());
|
ImGuiStringViewText(entry.name);
|
||||||
}
|
|
||||||
if (ImGui::TableNextColumn()) {
|
|
||||||
ImGuiStringViewText(ent->GetName());
|
|
||||||
}
|
}
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText(ScriptObjectStateToStr(item.x0_state));
|
ImGuiStringViewText(ScriptObjectStateToStr(item.x0_state));
|
||||||
|
@ -228,12 +221,7 @@ void CEntity::ImGuiInspect() {
|
||||||
if (ImGui::TableNextColumn()) {
|
if (ImGui::TableNextColumn()) {
|
||||||
ImGuiStringViewText(ScriptObjectMessageToStr(item.x4_msg));
|
ImGuiStringViewText(ScriptObjectMessageToStr(item.x4_msg));
|
||||||
}
|
}
|
||||||
if (ImGui::TableNextColumn()) {
|
ImGuiConsole::EndEntityRow(entry);
|
||||||
if (ImGui::SmallButton("View")) {
|
|
||||||
ImGuiConsole::inspectingEntities.insert(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
}
|
}
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -908,7 +908,7 @@ bool CMain::Proc(float dt) {
|
||||||
m_loadedPersistentResources = true;
|
m_loadedPersistentResources = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_imGuiConsole->proc();
|
m_imGuiConsole->PreUpdate();
|
||||||
|
|
||||||
if (!m_paused) {
|
if (!m_paused) {
|
||||||
CGBASupport::GlobalPoll();
|
CGBASupport::GlobalPoll();
|
||||||
|
@ -918,6 +918,8 @@ bool CMain::Proc(float dt) {
|
||||||
CStreamAudioManager::Update(dt);
|
CStreamAudioManager::Update(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_imGuiConsole->PostUpdate();
|
||||||
|
|
||||||
if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) {
|
if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) {
|
||||||
CStreamAudioManager::StopAll();
|
CStreamAudioManager::StopAll();
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -221,7 +221,7 @@ void CActor::RenderInternal(const CStateManager& mgr) const {
|
||||||
|
|
||||||
zeus::CColor mulColor(mulMag * xb4_drawFlags.x4_color.a(), xb4_drawFlags.x4_color.a());
|
zeus::CColor mulColor(mulMag * xb4_drawFlags.x4_color.a(), xb4_drawFlags.x4_color.a());
|
||||||
zeus::CColor addColor(addMag, xb4_drawFlags.x4_color.a() / 4.f);
|
zeus::CColor addColor(addMag, xb4_drawFlags.x4_color.a() / 4.f);
|
||||||
if (m_debugSelected) {
|
if (m_debugSelected || m_debugHovered) {
|
||||||
addColor += m_debugAddColor;
|
addColor += m_debugAddColor;
|
||||||
}
|
}
|
||||||
x64_modelData->RenderThermal(x34_transform, mulColor, addColor, xb4_drawFlags);
|
x64_modelData->RenderThermal(x34_transform, mulColor, addColor, xb4_drawFlags);
|
||||||
|
@ -234,7 +234,7 @@ void CActor::RenderInternal(const CStateManager& mgr) const {
|
||||||
1.f),
|
1.f),
|
||||||
1.f);
|
1.f);
|
||||||
CModelFlags flags(2, xb4_drawFlags.x1_matSetIdx, xb4_drawFlags.x2_flags, color);
|
CModelFlags flags(2, xb4_drawFlags.x1_matSetIdx, xb4_drawFlags.x2_flags, color);
|
||||||
if (m_debugSelected) {
|
if (m_debugSelected || m_debugHovered) {
|
||||||
flags.addColor += m_debugAddColor;
|
flags.addColor += m_debugAddColor;
|
||||||
}
|
}
|
||||||
x64_modelData->Render(mgr, x34_transform, x90_actorLights.get(), flags);
|
x64_modelData->Render(mgr, x34_transform, x90_actorLights.get(), flags);
|
||||||
|
@ -242,7 +242,7 @@ void CActor::RenderInternal(const CStateManager& mgr) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CModelFlags flags = xb4_drawFlags;
|
CModelFlags flags = xb4_drawFlags;
|
||||||
if (m_debugSelected) {
|
if (m_debugSelected || m_debugHovered) {
|
||||||
flags.addColor += m_debugAddColor;
|
flags.addColor += m_debugAddColor;
|
||||||
}
|
}
|
||||||
x64_modelData->Render(which, x34_transform, x90_actorLights.get(), flags);
|
x64_modelData->Render(which, x34_transform, x90_actorLights.get(), flags);
|
||||||
|
|
|
@ -26,6 +26,7 @@ class CSimpleShadow;
|
||||||
|
|
||||||
class CActor : public CEntity {
|
class CActor : public CEntity {
|
||||||
friend class CStateManager;
|
friend class CStateManager;
|
||||||
|
friend class ImGuiConsole;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
zeus::CTransform x34_transform;
|
zeus::CTransform x34_transform;
|
||||||
|
@ -74,6 +75,8 @@ protected:
|
||||||
bool xe7_31_targetable : 1 = true;
|
bool xe7_31_targetable : 1 = true;
|
||||||
|
|
||||||
boo::ObjToken<boo::ITextureCubeR> m_reflectionCube;
|
boo::ObjToken<boo::ITextureCubeR> m_reflectionCube;
|
||||||
|
zeus::CColor m_debugAddColor = zeus::skClear;
|
||||||
|
float m_debugAddColorTime = 0.f;
|
||||||
|
|
||||||
void _CreateShadow();
|
void _CreateShadow();
|
||||||
void _CreateReflectionCube();
|
void _CreateReflectionCube();
|
||||||
|
@ -83,10 +86,6 @@ protected:
|
||||||
bool IsModelOpaque(const CStateManager& mgr) const;
|
bool IsModelOpaque(const CStateManager& mgr) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool m_debugSelected = false;
|
|
||||||
zeus::CColor m_debugAddColor = zeus::skClear;
|
|
||||||
float m_debugAddColorTime = 0.f;
|
|
||||||
|
|
||||||
enum class EFluidState { EnteredFluid, InFluid, LeftFluid };
|
enum class EFluidState { EnteredFluid, InFluid, LeftFluid };
|
||||||
|
|
||||||
enum class EScanState {
|
enum class EScanState {
|
||||||
|
|
|
@ -28,6 +28,7 @@ class IVisitor;
|
||||||
class CEntity {
|
class CEntity {
|
||||||
friend class CStateManager;
|
friend class CStateManager;
|
||||||
friend class CObjectList;
|
friend class CObjectList;
|
||||||
|
friend class ImGuiConsole;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TAreaId x4_areaId;
|
TAreaId x4_areaId;
|
||||||
|
@ -40,6 +41,10 @@ protected:
|
||||||
bool x30_26_scriptingBlocked : 1 = false;
|
bool x30_26_scriptingBlocked : 1 = false;
|
||||||
bool x30_27_inUse : 1;
|
bool x30_27_inUse : 1;
|
||||||
|
|
||||||
|
// Used in ImGuiConsole
|
||||||
|
bool m_debugSelected = false;
|
||||||
|
bool m_debugHovered = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const std::vector<SConnection> NullConnectionList;
|
static const std::vector<SConnection> NullConnectionList;
|
||||||
virtual ~CEntity() = default;
|
virtual ~CEntity() = default;
|
||||||
|
|
Loading…
Reference in New Issue