Merge pull request #3208 from garrettjoecox/valueViewer

MVP ValueViewer
This commit is contained in:
Garrett Cox 2023-11-24 12:25:39 -06:00 committed by GitHub
commit bdc6fad0a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,219 @@
#include "valueViewer.h"
#include "../../UIWidgets.hpp"
extern "C" {
#include <z64.h>
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState;
void GfxPrint_SetColor(GfxPrint* printer, u32 r, u32 g, u32 b, u32 a);
void GfxPrint_SetPos(GfxPrint* printer, s32 x, s32 y);
s32 GfxPrint_Printf(GfxPrint* printer, const char* fmt, ...);
}
ImVec4 WHITE = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
std::vector<ValueTableElement> valueTable = {
{ "Time", "gSaveContext.dayTime", "TIME:", TYPE_U16, false, []() -> void* { return &gSaveContext.dayTime; }, WHITE },
{ "Age", "gSaveContext.linkAge", "AGE:", TYPE_S32, false, []() -> void* { return &gSaveContext.linkAge; }, WHITE },
{ "Health", "gSaveContext.health", "HP:", TYPE_S16, false, []() -> void* { return &gSaveContext.health; }, WHITE },
{ "Navi Timer", "gSaveContext.naviTimer", "NAVI:", TYPE_U16, false, []() -> void* { return &gSaveContext.naviTimer; }, WHITE },
{ "Scene ID", "play->sceneNum", "SCENE:", TYPE_S16, true, []() -> void* { return &gPlayState->sceneNum; }, WHITE },
{ "Room ID", "play->roomCtx.curRoom.num", "ROOM:", TYPE_S8, true, []() -> void* { return &gPlayState->roomCtx.curRoom.num; }, WHITE },
{ "Entrance ID", "gSaveContext.entranceIndex", "ENTR:", TYPE_S32, false, []() -> void* { return &gSaveContext.entranceIndex; }, WHITE },
{ "Cutscene ID", "gSaveContext.cutsceneIndex", "CUTS:", TYPE_S32, false, []() -> void* { return &gSaveContext.cutsceneIndex; }, WHITE },
{ "Link X", "Player->actor.world.pos.x", "X:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.x; }, WHITE },
{ "Link Y", "Player->actor.world.pos.y", "Y:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.y; }, WHITE },
{ "Link Z", "Player->actor.world.pos.z", "Z:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.pos.z; }, WHITE },
{ "Link Yaw", "Player->actor.world.rot.y", "ROT:", TYPE_S16, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.world.rot.y; }, WHITE },
{ "Link Velocity", "Player->linearVelocity", "V:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->linearVelocity; }, WHITE },
{ "Link X Velocity", "Player->actor.velocity.x", "XV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.x; }, WHITE },
{ "Link Y Velocity", "Player->actor.velocity.y", "YV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.y; }, WHITE },
{ "Link Z Velocity", "Player->actor.velocity.z", "ZV:", TYPE_FLOAT, true, []() -> void* { return &GET_PLAYER(gPlayState)->actor.velocity.z; }, WHITE },
{ "Text ID", "play->msgCtx.textId", "TEXTID:", TYPE_U16, true, []() -> void* { return &gPlayState->msgCtx.textId; }, WHITE },
{ "Analog Stick X", "play->state.input->cur.stick_x", "AX:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_x; }, WHITE },
{ "Analog Stick Y", "play->state.input->cur.stick_y", "AY:", TYPE_S8, true, []() -> void* { return &gPlayState->state.input->cur.stick_y; }, WHITE },
/* TODO: Find these (from GZ)
"XZ Units Traveled (Camera based speed variable)" f32 0x801C9018
"Movement Angle" x16 0x801DBB1C
"Camera Angle" u16 0x801C907C
"Time of Day" x16 0x8011AC8C
"Global Frame Counter" s32 0x801C8DFC
"Lit Deku Stick Timer" u16 0x801DBB40
"Cutscene Pointer" u32 0x801CAAC8
"Get Item Value" s8 0x801DB714
"Last RNG Value" x32 0x80105A80
"Last Item Button Pressed" u8 0x801DB430
"Last Damage Value" x32 0x801DB7DC
"Temp B Value" u8 0x8011C062
"Framerate Divisor" u8 0x801C7861
"Heads Up Display (HUD)" u16 0x8011C068
"Analog Stick Angle" s16 0x803AA698
"Deku Tree Warp Timer (Reload Room)" u16 0x801F0352
"Dodongo's Cavern Warp Timer" u16 0x801E30B2
"Jabu-Jabu Warp Timer" u16 0x802008B2
"Forest Temple Warp Timer" u16 0x801EC5B2
"Fire Temple Warp Timer" u16 0x801F3E42
"Water Temple Warp Timer" u16 0x801F8762
"Shadow Temple Warp Timer" u16 0x801F48A2
"Spirit Temple Warp Timer" u16 0x801FD562
"Deku Tree Warp Timer" u16 0x801F83A2
*/
};
extern "C" void ValueViewer_Draw(GfxPrint* printer) {
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || !element.isPrinted || (gPlayState == NULL && element.requiresPlayState)) continue;
GfxPrint_SetColor(printer, element.color.x * 255, element.color.y * 255, element.color.z * 255, element.color.w * 255);
GfxPrint_SetPos(printer, element.x, element.y);
switch (element.type) {
case TYPE_S8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s8*)element.valueFn());
break;
case TYPE_U8:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u8*)element.valueFn());
break;
case TYPE_S16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s16*)element.valueFn());
break;
case TYPE_U16:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u16*)element.valueFn());
break;
case TYPE_S32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%d"), element.prefix.c_str(), *(s32*)element.valueFn());
break;
case TYPE_U32:
GfxPrint_Printf(printer, (element.typeFormat ? "%s0x%x" : "%s%u"), element.prefix.c_str(), *(u32*)element.valueFn());
break;
case TYPE_CHAR:
GfxPrint_Printf(printer, "%s%c", element.prefix.c_str(), *(char*)element.valueFn());
break;
case TYPE_STRING:
GfxPrint_Printf(printer, "%s%s", element.prefix.c_str(), (char*)element.valueFn());
break;
case TYPE_FLOAT:
GfxPrint_Printf(printer, (element.typeFormat ? "%s%4.1f" : "%s%f"), element.prefix.c_str(), *(float*)element.valueFn());
break;
}
}
}
void ValueViewerWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Value Viewer", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
UIWidgets::PaddedEnhancementCheckbox("Enable Printing", "gValueViewer.EnablePrinting");
ImGui::BeginGroup();
static int selectedElement = -1;
std::string selectedElementText = (selectedElement == -1) ? "Select a value" : (
std::string(valueTable[selectedElement].name) + " (" + std::string(valueTable[selectedElement].path) + ")"
);
if (ImGui::BeginCombo("##valueViewerElement", selectedElementText.c_str())) {
for (int i = 0; i < valueTable.size(); i++) {
if (valueTable[i].isActive) continue;
bool isSelected = (selectedElement == i);
std::string elementText = (
std::string(valueTable[i].name) + " (" + std::string(valueTable[i].path) + ")"
);
if (ImGui::Selectable(elementText.c_str(), isSelected)) {
selectedElement = i;
}
if (isSelected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
if (selectedElement != -1 && ImGui::Button("+")) {
valueTable[selectedElement].isActive = true;
selectedElement = -1;
}
ImGui::EndGroup();
for (int i = 0; i < valueTable.size(); i++) {
ValueTableElement& element = valueTable[i];
if (!element.isActive || (gPlayState == NULL && element.requiresPlayState)) continue;
if (ImGui::Button(("x##" + std::string(element.name)).c_str())) {
element.isActive = false;
element.isPrinted = false;
}
ImGui::SameLine();
ImGui::Text("%s:", element.name);
ImGui::SameLine();
switch (element.type) {
case TYPE_S8:
ImGui::Text(element.typeFormat ? "0x%x" : "%d", *(s8*)element.valueFn());
break;
case TYPE_U8:
ImGui::Text(element.typeFormat ? "0x%x" : "%u", *(u8*)element.valueFn());
break;
case TYPE_S16:
ImGui::Text(element.typeFormat ? "0x%x" : "%d", *(s16*)element.valueFn());
break;
case TYPE_U16:
ImGui::Text(element.typeFormat ? "0x%x" : "%u", *(u16*)element.valueFn());
break;
case TYPE_S32:
ImGui::Text(element.typeFormat ? "0x%x" : "%d", *(s32*)element.valueFn());
break;
case TYPE_U32:
ImGui::Text(element.typeFormat ? "0x%x" : "%u", *(u32*)element.valueFn());
break;
case TYPE_CHAR:
ImGui::Text("%c", *(char*)element.valueFn());
break;
case TYPE_STRING:
ImGui::Text("%s", (char*)element.valueFn());
break;
case TYPE_FLOAT:
ImGui::Text(element.typeFormat ? "%4.1f" : "%f", *(float*)element.valueFn());
break;
}
ImGui::SameLine();
if (element.type <= TYPE_U32) {
ImGui::Checkbox(("Hex##" + std::string(element.name)).c_str(), &element.typeFormat);
ImGui::SameLine();
} else if (element.type == TYPE_FLOAT) {
ImGui::Checkbox(("Trim##" + std::string(element.name)).c_str(), &element.typeFormat);
ImGui::SameLine();
}
ImGui::BeginGroup();
if (CVarGetInteger("gValueViewer.EnablePrinting", 0)) {
ImGui::Checkbox(("Print##" + std::string(element.name)).c_str(), &element.isPrinted);
if (element.isPrinted) {
char* prefix = (char*)element.prefix.c_str();
ImGui::SameLine();
ImGui::SetNextItemWidth(80.0f);
if (ImGui::InputText(("Prefix##" + std::string(element.name)).c_str(), prefix, 10)) {
element.prefix = prefix;
}
ImGui::SameLine();
ImGui::ColorEdit3(("##color" + std::string(element.name)).c_str(), (float*)&element.color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
ImGui::SameLine();
if (ImGui::Button(("Position##" + std::string(element.name)).c_str())) {
ImGui::OpenPopup(("Position Picker##" + std::string(element.name)).c_str());
}
if (ImGui::BeginPopup(("Position Picker##" + std::string(element.name)).c_str())) {
ImGui::DragInt("X", (int*)&element.x, 1.0f, 0, 44);
ImGui::DragInt("Y", (int*)&element.y, 1.0f, 0, 29);
ImGui::EndPopup();
}
}
}
ImGui::EndGroup();
}
ImGui::End();
}
void ValueViewerWindow::InitElement() {
}

View File

@ -0,0 +1,53 @@
#pragma once
#ifdef __cplusplus
#include <libultraship/libultraship.h>
typedef enum {
TYPE_S8,
TYPE_U8,
TYPE_S16,
TYPE_U16,
TYPE_S32,
TYPE_U32,
TYPE_CHAR,
TYPE_STRING,
TYPE_FLOAT,
} ValueType;
typedef void* (*ValueFn)();
typedef struct {
const char* name;
const char* path;
std::string prefix;
ValueType type;
bool requiresPlayState;
ValueFn valueFn;
ImVec4 color;
bool isActive;
bool isPrinted;
bool typeFormat;
uint32_t x;
uint32_t y;
} ValueTableElement;
class ValueViewerWindow : public LUS::GuiWindow {
public:
using GuiWindow::GuiWindow;
void InitElement() override;
void DrawElement() override;
void UpdateElement() override {};
};
extern "C" {
#include <z64.h>
#endif
void ValueViewer_Draw(GfxPrint* printer);
#ifdef __cplusplus
}
#endif

View File

@ -118,6 +118,7 @@ namespace SohGui {
std::shared_ptr<ColViewerWindow> mColViewerWindow;
std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
std::shared_ptr<DLViewerWindow> mDLViewerWindow;
std::shared_ptr<ValueViewerWindow> mValueViewerWindow;
std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
std::shared_ptr<CheckTracker::CheckTrackerSettingsWindow> mCheckTrackerSettingsWindow;
std::shared_ptr<CheckTracker::CheckTrackerWindow> mCheckTrackerWindow;
@ -169,6 +170,8 @@ namespace SohGui {
gui->AddGuiWindow(mSaveEditorWindow);
mDLViewerWindow = std::make_shared<DLViewerWindow>("gDLViewerEnabled", "Display List Viewer");
gui->AddGuiWindow(mDLViewerWindow);
mValueViewerWindow = std::make_shared<ValueViewerWindow>("gValueViewer.WindowOpen", "Value Viewer");
gui->AddGuiWindow(mValueViewerWindow);
mGameplayStatsWindow = std::make_shared<GameplayStatsWindow>("gGameplayStatsEnabled", "Gameplay Stats");
gui->AddGuiWindow(mGameplayStatsWindow);
mCheckTrackerWindow = std::make_shared<CheckTracker::CheckTrackerWindow>("gCheckTrackerEnabled", "Check Tracker");
@ -194,6 +197,7 @@ namespace SohGui {
mCheckTrackerSettingsWindow = nullptr;
mGameplayStatsWindow = nullptr;
mDLViewerWindow = nullptr;
mValueViewerWindow = nullptr;
mSaveEditorWindow = nullptr;
mColViewerWindow = nullptr;
mActorViewerWindow = nullptr;

View File

@ -17,6 +17,7 @@
#include "Enhancements/debugger/colViewer.h"
#include "Enhancements/debugger/debugSaveEditor.h"
#include "Enhancements/debugger/dlViewer.h"
#include "Enhancements/debugger/valueViewer.h"
#include "Enhancements/gameplaystatswindow.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"

View File

@ -22,6 +22,7 @@
#include "Enhancements/debugger/colViewer.h"
#include "Enhancements/debugger/debugSaveEditor.h"
#include "Enhancements/debugger/dlViewer.h"
#include "Enhancements/debugger/valueViewer.h"
#include "Enhancements/gameplaystatswindow.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
@ -1407,6 +1408,7 @@ extern std::shared_ptr<SaveEditorWindow> mSaveEditorWindow;
extern std::shared_ptr<ColViewerWindow> mColViewerWindow;
extern std::shared_ptr<ActorViewerWindow> mActorViewerWindow;
extern std::shared_ptr<DLViewerWindow> mDLViewerWindow;
extern std::shared_ptr<ValueViewerWindow> mValueViewerWindow;
void DrawDeveloperToolsMenu() {
if (ImGui::BeginMenu("Developer Tools")) {
@ -1478,6 +1480,12 @@ void DrawDeveloperToolsMenu() {
mDLViewerWindow->ToggleVisibility();
}
}
UIWidgets::Spacer(0);
if (mValueViewerWindow) {
if (ImGui::Button(GetWindowButtonText("Value Viewer", CVarGetInteger("gValueViewer.WindowOpen", 0)).c_str(), ImVec2(-1.0f, 0.0f))) {
mValueViewerWindow->ToggleVisibility();
}
}
ImGui::PopStyleVar(3);
ImGui::PopStyleColor(1);

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include "soh/Enhancements/debugger/colViewer.h"
#include "soh/Enhancements/debugger/valueViewer.h"
#include "soh/Enhancements/gameconsole.h"
#include "soh/OTRGlobals.h"
@ -289,6 +290,28 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
OPEN_DISPS(gfxCtx);
if (CVarGetInteger("gValueViewer.EnablePrinting", 0)) {
Gfx* gfx;
Gfx* polyOpa;
GfxPrint printer;
polyOpa = POLY_OPA_DISP;
gfx = Graph_GfxPlusOne(polyOpa);
gSPDisplayList(OVERLAY_DISP++, gfx);
GfxPrint_Init(&printer);
GfxPrint_Open(&printer, gfx);
ValueViewer_Draw(&printer);
gfx = GfxPrint_Close(&printer);
GfxPrint_Destroy(&printer);
gSPEndDisplayList(gfx++);
Graph_BranchDlist(polyOpa, gfx);
POLY_OPA_DISP = gfx;
}
gDPNoOpString(WORK_DISP++, "WORK_DISP 終了", 0);
gDPNoOpString(POLY_OPA_DISP++, "POLY_OPA_DISP 終了", 0);
gDPNoOpString(POLY_XLU_DISP++, "POLY_XLU_DISP 終了", 0);