Implement ConsoleVariables window

This commit is contained in:
Phillip Stephens 2021-05-30 17:15:22 -07:00
parent bed05b1357
commit 882a58202e
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
5 changed files with 266 additions and 37 deletions

View File

@ -149,29 +149,29 @@ void CTweakAutoMapper::initCVars(hecl::CVarManager* mgr) {
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_widgetColor = assignColorValue(skWidgetColor, "", x38_automapperWidgetMiniColor,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_visitedsurfaceColor =
assignColorValue(skVisitedSurfaceColor, "", x3c_surfColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_visitedOutlineColor =
assignColorValue(skVisitedOutlineColor, "", x40_outlineColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_unvisitedSurfaceColor =
assignColorValue(skUnvisitedSurfaceColor, "", x44_surfColorUnvisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_visitedsurfaceColor = assignColorValue(skVisitedSurfaceColor, "", x3c_surfColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_visitedOutlineColor = assignColorValue(skVisitedOutlineColor, "", x40_outlineColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_unvisitedSurfaceColor = assignColorValue(skUnvisitedSurfaceColor, "", x44_surfColorUnvisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_unvisitedOutlineColor =
assignColorValue(skUnvisitedOutlineColor, "", x48_outlineColorUnvisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_selectedVisitedSurfaceColor =
assignColorValue(skSelectedVisitedSurfaceColor, "", x4c_surfaceSelectColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_selectedVisitedOutlineColor =
assignColorValue(skSelectedVisitedOutlineColor, "", x50_outlineSelectColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_mapSurfaceNormColorLinear =
assignRealValue(skMapSurfaceNormalColorLinear, "", x54_mapSurfaceNormColorLinear,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_mapSurfaceNormColorConstant =
assignRealValue(skMapSurfaceNormalColorConstant, "", x58_mapSurfaceNormColorConstant,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_selectedVisitedSurfaceColor = assignColorValue(skSelectedVisitedSurfaceColor, "", x4c_surfaceSelectColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_selectedVisitedOutlineColor = assignColorValue(skSelectedVisitedOutlineColor, "", x50_outlineSelectColorVisited,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_mapSurfaceNormColorLinear = assignRealValue(skMapSurfaceNormalColorLinear, "", x54_mapSurfaceNormColorLinear,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
tw_mapSurfaceNormColorConstant = assignRealValue(skMapSurfaceNormalColorConstant, "", x58_mapSurfaceNormColorConstant,
hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Color |
hecl::CVar::EFlags::Gui | hecl::CVar::EFlags::Archive);
}
}
} // namespace DataSpec::DNAMP1

View File

@ -6,6 +6,7 @@
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "magic_enum.hpp"
#include "ImGuiEngine.hpp"
namespace ImGui {
@ -353,6 +354,229 @@ bool ImGuiConsole::ShowEntityInfoWindow(TUniqueId uid) {
return open;
}
void ImGuiConsole::ShowConsoleVariablesWindow() {
// For some reason the window shows up tiny without this
float initialWindowSize = 350.f * ImGui::GetIO().DisplayFramebufferScale.x;
ImGui::SetNextWindowSize(ImVec2{initialWindowSize, initialWindowSize}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Console Variables", &m_showConsoleVariablesWindow)) {
if (ImGui::Button("Clear")) {
m_cvarFiltersText[0] = '\0';
}
ImGui::SameLine();
ImGui::InputText("Filter", m_cvarFiltersText.data(), m_cvarFiltersText.size());
auto cvars = m_cvarMgr.cvars(hecl::CVar::EFlags::Any & ~hecl::CVar::EFlags::Hidden);
if (ImGui::BeginTable("ConsoleVariables", 2,
ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_RowBg |
ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupColumn("Name",
ImGuiTableColumnFlags_PreferSortAscending | ImGuiTableColumnFlags_DefaultSort |
ImGuiTableColumnFlags_WidthFixed,
0, 'name');
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch, 0, 'val');
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableHeadersRow();
ImGuiTableSortSpecs* sortSpecs = ImGui::TableGetSortSpecs();
bool hasSortSpec = sortSpecs != nullptr &&
// no multi-sort
sortSpecs->SpecsCount == 1;
std::string_view search{m_cvarFiltersText.data(), strlen(m_cvarFiltersText.data())};
std::vector<hecl::CVar*> sortedList;
sortedList.reserve(cvars.size());
for (auto* cvar : cvars) {
if (!search.empty()) {
if (ContainsCaseInsensitive(magic_enum::enum_name(cvar->type()), search) ||
ContainsCaseInsensitive(cvar->name(), search)) {
sortedList.push_back(cvar);
}
} else {
sortedList.push_back(cvar);
}
}
if (hasSortSpec) {
const auto& spec = sortSpecs->Specs[0];
if (spec.ColumnUserID == 'name') {
std::sort(sortedList.begin(), sortedList.end(), [&](hecl::CVar* a, hecl::CVar* b) {
int compare = a->name().compare(b->name());
return spec.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
});
} else if (spec.ColumnUserID == 'val') {
std::sort(sortedList.begin(), sortedList.end(), [&](hecl::CVar* a, hecl::CVar* b) {
int compare = a->value().compare(b->value());
return spec.SortDirection == ImGuiSortDirection_Ascending ? compare < 0 : compare > 0;
});
}
for (auto* cv : sortedList) {
ImGui::PushID(cv);
ImGui::TableNextRow();
// Name
if (ImGui::TableNextColumn()) {
ImGuiStringViewText(cv->name());
if (ImGui::IsItemHovered() && !cv->rawHelp().empty()) {
std::string sv(cv->rawHelp());
ImGui::SetTooltip("%s", sv.c_str());
}
}
// Value
if (ImGui::TableNextColumn()) {
switch (cv->type()) {
case hecl::CVar::EType::Boolean: {
bool b = cv->toBoolean();
if (ImGui::Checkbox("", &b)) {
cv->fromBoolean(b);
}
break;
}
case hecl::CVar::EType::Real: {
float f = cv->toReal();
if (ImGui::DragFloat("", &f)) {
cv->fromReal(f);
}
break;
}
case hecl::CVar::EType::Signed: {
std::array<s32, 1> i{cv->toSigned()};
if (ImGui::DragScalar("", ImGuiDataType_S32, i.data(), i.size())) {
cv->fromInteger(i[0]);
}
break;
}
case hecl::CVar::EType::Unsigned: {
std::array<u32, 1> i{cv->toUnsigned()};
if (ImGui::DragScalar("", ImGuiDataType_U32, i.data(), i.size())) {
cv->fromInteger(i[0]);
}
break;
}
case hecl::CVar::EType::Literal: {
char buf[4096];
strcpy(buf, cv->value().c_str());
if (ImGui::InputText("", buf, 4096, ImGuiInputTextFlags_EnterReturnsTrue)) {
cv->fromLiteral(buf);
}
break;
}
case hecl::CVar::EType::Vec2f: {
auto vec = cv->toVec2f();
std::array<float, 2> scalars = {vec.simd[0], vec.simd[1]};
if (ImGui::DragScalarN("", ImGuiDataType_Float, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
cv->fromVec2f(vec);
}
break;
}
case hecl::CVar::EType::Vec2d: {
auto vec = cv->toVec2d();
std::array<double, 2> scalars = {vec.simd[0], vec.simd[1]};
if (ImGui::DragScalarN("", ImGuiDataType_Double, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
cv->fromVec2d(vec);
}
break;
}
case hecl::CVar::EType::Vec3f: {
auto vec = cv->toVec3f();
std::array<float, 3> scalars = {vec.simd[0], vec.simd[1]};
if (cv->isColor()) {
if (ImGui::ColorEdit3("", scalars.data())) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
cv->fromVec3f(vec);
}
} else if (ImGui::DragScalarN("", ImGuiDataType_Float, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
cv->fromVec3f(vec);
}
break;
}
case hecl::CVar::EType::Vec3d: {
auto vec = cv->toVec3d();
std::array<double, 3> scalars = {vec.simd[0], vec.simd[1], vec.simd[2]};
if (cv->isColor()) {
std::array<float, 3> color{static_cast<float>(scalars[0]), static_cast<float>(scalars[1]),
static_cast<float>(scalars[2])};
if (ImGui::ColorEdit3("", color.data())) {
vec.simd[0] = color[0];
vec.simd[1] = color[1];
vec.simd[2] = color[2];
cv->fromVec3d(vec);
}
} else if (ImGui::DragScalarN("", ImGuiDataType_Double, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
cv->fromVec3d(vec);
}
break;
}
case hecl::CVar::EType::Vec4f: {
auto vec = cv->toVec4f();
std::array<float, 4> scalars = {vec.simd[0], vec.simd[1], vec.simd[2], vec.simd[3]};
if (cv->isColor()) {
if (ImGui::ColorEdit4("", scalars.data())) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
cv->fromVec4f(vec);
}
} else if (ImGui::DragScalarN("", ImGuiDataType_Float, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
vec.simd[3] = scalars[3];
cv->fromVec4f(vec);
}
break;
}
case hecl::CVar::EType::Vec4d: {
auto vec = cv->toVec4d();
std::array<double, 4> scalars = {vec.simd[0], vec.simd[1], vec.simd[2], vec.simd[3]};
if (cv->isColor()) {
std::array<float, 4> color{static_cast<float>(scalars[0]), static_cast<float>(scalars[1]),
static_cast<float>(scalars[2]), static_cast<float>(scalars[3])};
if (ImGui::ColorEdit4("", color.data())) {
vec.simd[0] = color[0];
vec.simd[1] = color[1];
vec.simd[2] = color[2];
vec.simd[3] = color[3];
cv->fromVec4d(vec);
}
} else if (ImGui::DragScalarN("", ImGuiDataType_Double, scalars.data(), scalars.size(), 0.1f)) {
vec.simd[0] = scalars[0];
vec.simd[1] = scalars[1];
vec.simd[2] = scalars[2];
vec.simd[3] = scalars[3];
cv->fromVec4d(vec);
}
break;
}
default:
ImGui::Text("lawl wut? Please contact a developer, your copy of Metaforce is cursed!");
break;
}
if (ImGui::IsItemHovered() && cv->hasDefaultValue()) {
std::string sv(cv->defaultValue());
ImGui::SetTooltip("Default: %s", sv.c_str());
}
}
ImGui::PopID();
}
}
ImGui::EndTable();
}
}
ImGui::End();
}
void ImGuiConsole::ShowAboutWindow(bool canClose, std::string_view errorString) {
// Center window
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
@ -771,9 +995,10 @@ void ImGuiConsole::ShowAppMainMenuBar(bool canInspect) {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Tools")) {
ImGui::MenuItem("Inspect", nullptr, &m_showInspectWindow, canInspect);
ImGui::MenuItem("Items", nullptr, &m_showItemsWindow, canInspect);
ImGui::MenuItem("Layers", nullptr, &m_showLayersWindow, canInspect);
ImGui::MenuItem("Inspect", nullptr, &m_showInspectWindow, canInspect && m_developer);
ImGui::MenuItem("Items", nullptr, &m_showItemsWindow, canInspect && m_developer && m_cheats);
ImGui::MenuItem("Layers", nullptr, &m_showLayersWindow, canInspect && m_developer);
ImGui::MenuItem("Console Variables", nullptr, &m_showConsoleVariablesWindow);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Debug")) {
@ -828,7 +1053,7 @@ void ImGuiConsole::ShowAppMainMenuBar(bool canInspect) {
void ImGuiConsole::PreUpdate() {
// We ned to make sure we have a valid CRandom16 at all times, so lets do that here
if (g_StateManager && g_StateManager->GetActiveRandom() == nullptr) {
if (g_StateManager != nullptr && g_StateManager->GetActiveRandom() == nullptr) {
g_StateManager->SetActiveRandomToDefault();
}
@ -852,7 +1077,7 @@ void ImGuiConsole::PreUpdate() {
}
}
}
if (canInspect && m_showItemsWindow) {
if (canInspect && m_showItemsWindow && m_cvarMgr.findCVar("cheats")->toBoolean()) {
ShowItemsWindow();
}
if (canInspect && m_showLayersWindow) {
@ -864,6 +1089,9 @@ void ImGuiConsole::PreUpdate() {
if (m_showDemoWindow) {
ImGui::ShowDemoWindow(&m_showDemoWindow);
}
if (m_showConsoleVariablesWindow) {
ShowConsoleVariablesWindow();
}
ShowDebugOverlay();
}

View File

@ -53,6 +53,7 @@ private:
bool m_showAboutWindow = false;
bool m_showItemsWindow = false;
bool m_showLayersWindow = false;
bool m_showConsoleVariablesWindow = false;
bool m_paused = false;
bool m_stepFrame = false;
@ -61,6 +62,7 @@ private:
bool m_inspectCurrentAreaOnly = false;
std::array<char, 40> m_inspectFilterText{};
std::array<char, 40> m_layersFilterText{};
std::array<char, 40> m_cvarFiltersText{};
// Debug overlays
bool m_frameCounter = m_cvarCommons.m_debugOverlayShowFrameCounter->toBoolean();
@ -73,6 +75,8 @@ private:
bool m_randomStats = m_cvarCommons.m_debugOverlayShowRandomStats->toBoolean();
bool m_resourceStats = m_cvarCommons.m_debugOverlayShowResourceStats->toBoolean();
bool m_showInput = m_cvarCommons.m_debugOverlayShowInput->toBoolean();
const bool m_developer = m_cvarMgr.findCVar("developer")->toBoolean();
const bool m_cheats = m_cvarMgr.findCVar("cheats")->toBoolean();
int m_debugOverlayCorner = 2; // bottom-left
const void* m_currentRoom = nullptr;
@ -88,5 +92,6 @@ private:
void ShowDebugOverlay();
void ShowItemsWindow();
void ShowLayersWindow();
void ShowConsoleVariablesWindow();
};
} // namespace metaforce

View File

@ -72,6 +72,7 @@ public:
std::string_view name() const { return m_name; }
std::string_view rawHelp() const { return m_help; }
std::string_view defaultValue() const { return m_defaultValue; }
std::string help() const;
std::string value() const { return m_value; }

View File

@ -415,9 +415,7 @@ bool CVar::fromLiteralToType(std::string_view val) {
return true;
}
bool CVar::fromLiteralToType(std::wstring_view val) {
return fromLiteralToType(hecl::WideToUTF8(val));
}
bool CVar::fromLiteralToType(std::wstring_view val) { return fromLiteralToType(hecl::WideToUTF8(val)); }
bool CVar::isModified() const { return True(m_flags & EFlags::Modified); }
bool CVar::modificationRequiresRestart() const { return True(m_flags & EFlags::ModifyRestart); }
@ -433,8 +431,8 @@ bool CVar::isArchive() const { return True(m_flags & EFlags::Archive); }
bool CVar::isInternalArchivable() const { return True(m_flags & EFlags::InternalArchivable); }
bool CVar::isColor() const {
return True(m_flags & EFlags::Color) &&
(m_type == EType::Vec3f || m_type == EType::Vec3d || m_type == EType::Vec3f || m_type == EType::Vec4d);
return True(m_flags & EFlags::Color) && (m_type == EType::Vec3f || m_type == EType::Vec3d || m_type == EType::Vec3f ||
m_type == EType::Vec4f || m_type == EType::Vec4d);
}
bool CVar::isNoDeveloper() const { return True(m_flags & EFlags::NoDeveloper); }
@ -470,7 +468,6 @@ void CVar::dispatch() {
listen(this);
}
bool isReal(std::string_view v) {
char* p;
std::strtod(v.data(), &p);
@ -487,7 +484,7 @@ bool isReal(const std::vector<std::string>& v) {
bool CVar::isValidInput(std::string_view input) const {
std::vector<std::string> parts = athena::utility::split(input, ' ');
char* p;
switch(m_type) {
switch (m_type) {
case EType::Boolean: {
bool valid = false;
athena::utility::parseBool(input, &valid);
@ -520,9 +517,7 @@ bool CVar::isValidInput(std::string_view input) const {
return false;
}
bool CVar::isValidInput(std::wstring_view input) const {
return isValidInput(hecl::WideToUTF8(input));
}
bool CVar::isValidInput(std::wstring_view input) const { return isValidInput(hecl::WideToUTF8(input)); }
bool CVar::safeToModify(EType type) const {
// Are we NoDevelper?