From 3d24f3f5956a1fd920186c2d7c69e308089ff6f3 Mon Sep 17 00:00:00 2001 From: getBrainError Date: Fri, 17 Jun 2022 02:40:27 +0200 Subject: [PATCH] Improved Collision Viewer (#435) * Add fishing pole as sword in save editor Adds fishing pole as a sword to the save editor under current equipment. * Improve Collision Viewer Made all the values of the collision viewer persistent. Switched all color pickers to the EnhancementColor picker. Added a checkbox to enable/disable collision viewer. * Update SohImGuiImpl.cpp Probably fixed linux build error * Update colViewer.cpp Hopefully fixed it this time. Lets wait for jenkins. * Fixed colors Some color values were wrong * Update SohImGuiImpl.cpp & SohImGuiImpl.h --- libultraship/libultraship/SohImGuiImpl.cpp | 16 +- libultraship/libultraship/SohImGuiImpl.h | 1 + soh/soh/Enhancements/debugger/colViewer.cpp | 214 +++++++++----------- 3 files changed, 117 insertions(+), 114 deletions(-) diff --git a/libultraship/libultraship/SohImGuiImpl.cpp b/libultraship/libultraship/SohImGuiImpl.cpp index 463205c60..446082cbd 100644 --- a/libultraship/libultraship/SohImGuiImpl.cpp +++ b/libultraship/libultraship/SohImGuiImpl.cpp @@ -93,7 +93,7 @@ namespace SohImGui { "gCCHeartsPrim","gDDCCHeartsPrim", "gCCABtnPrim","gCCBBtnPrim","gCCCBtnPrim","gCCStartBtnPrim", "gCCMagicBorderPrim","gCCMagicPrim","gCCMagicUsePrim", - "gCCMinimapPrim","gCCRupeePrim","gCCKeysPrim" + "gCCMinimapPrim","gCCRupeePrim","gCCKeysPrim" }; const char* filters[3] = { @@ -556,6 +556,20 @@ namespace SohImGui { } } + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { + + if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { + for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { + if (ImGui::Selectable(items[settingIndex].c_str())) { + CVar_SetS32(cvarName, settingIndex); + needs_save = true; + + } + } + ImGui::EndCombo(); + } + } + void RandomizeColor(const char* cvarName, ImVec4* colors) { std::string Cvar_Red = cvarName; Cvar_Red += "R"; diff --git a/libultraship/libultraship/SohImGuiImpl.h b/libultraship/libultraship/SohImGuiImpl.h index 50d5c95e4..1ae02c1e7 100644 --- a/libultraship/libultraship/SohImGuiImpl.h +++ b/libultraship/libultraship/SohImGuiImpl.h @@ -72,6 +72,7 @@ namespace SohImGui { void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage); void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); void DrawMainMenuAndCalculateGameSize(void); diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index f5c283aac..91ea1f4b3 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include extern "C" { #include @@ -15,40 +16,27 @@ extern "C" { extern GlobalContext* gGlobalCtx; } -enum class ColRenderSetting { - Disabled, - Solid, - Transparent, - NumSettings -}; +enum class ColRenderSetting { Disabled, Solid, Transparent }; -std::string ColRenderSettingNames[] = { +std::vector ColRenderSettingNames = { "Disabled", "Solid", "Transparent", }; -static ColRenderSetting showSceneColSetting = ColRenderSetting::Disabled; -static ColRenderSetting showBgActorSetting = ColRenderSetting::Disabled; -static ColRenderSetting showColCheckSetting = ColRenderSetting::Disabled; -static ColRenderSetting showWaterboxSetting = ColRenderSetting::Disabled; +ImVec4 scene_col; +ImVec4 hookshot_col; +ImVec4 entrance_col; +ImVec4 specialSurface_col; +ImVec4 interactable_col; +ImVec4 slope_col; +ImVec4 void_col; -static uint32_t sceneColor = 0xFFFFFFFF; -static uint32_t hookshotColor = 0x8080FFFF; -static uint32_t entranceColor = 0x00FF00FF; -static uint32_t specialSurfaceColor = 0xC0FFC0FF; -static uint32_t interactableColor = 0xC000C0FF; -static uint32_t slopeColor = 0xFFFF80FF; -static uint32_t voidColor = 0xFF0000FF; +ImVec4 oc_col; +ImVec4 ac_col; +ImVec4 at_col; -static uint32_t ocColor = 0xFFFFFFFF; -static uint32_t acColor = 0x0000FFFF; -static uint32_t atColor = 0xFF0000FF; - -static uint32_t waterboxColor = 0x0000FFFF; - -static bool applyAsDecal = false; -static bool isShaded = false; +ImVec4 waterbox_col; static std::vector opaDl; static std::vector xluDl; @@ -62,35 +50,6 @@ static std::vector cylinderVtx; static std::vector sphereGfx; static std::vector sphereVtx; -// Create a dropdown menu to set a ColRenderSetting -void DrawColRenderSetting(const std::string& name, ColRenderSetting& setting) { - if (ImGui::BeginCombo(name.c_str(), ColRenderSettingNames[static_cast(setting)].c_str())) { - for (int32_t settingIndex = 0; settingIndex < static_cast(ColRenderSetting::NumSettings); settingIndex++) { - if (ImGui::Selectable(ColRenderSettingNames[settingIndex].c_str())) { - setting = static_cast(settingIndex); - } - } - ImGui::EndCombo(); - } -} - -// Draw a color picker box -void DrawColorPicker(const std::string& name, uint32_t& color) { - float colorAsFloat[4]; - colorAsFloat[0] = ((color >> 24) & 0xFF) / 255.0f; - colorAsFloat[1] = ((color >> 16) & 0xFF) / 255.0f; - colorAsFloat[2] = ((color >> 8) & 0xFF) / 255.0f; - colorAsFloat[3] = (color & 0xFF) / 255.0f; - if (ImGui::ColorEdit4(name.c_str(), colorAsFloat, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) { - color = static_cast(colorAsFloat[3] * 255) | - static_cast(colorAsFloat[2] * 255) << 8 | - static_cast(colorAsFloat[1] * 255) << 16 | - static_cast(colorAsFloat[0] * 255) << 24; - } - ImGui::SameLine(); - ImGui::Text(name.c_str()); -} - // Draws the ImGui window for the collision viewer void DrawColViewerWindow(bool& open) { if (!open) { @@ -102,16 +61,17 @@ void DrawColViewerWindow(bool& open) { ImGui::End(); return; } + SohImGui::EnhancementCheckbox("Enabled", "gColViewerEnabled"); - DrawColRenderSetting("Scene", showSceneColSetting); - DrawColRenderSetting("Bg Actors", showBgActorSetting); - DrawColRenderSetting("Col Check", showColCheckSetting); - DrawColRenderSetting("Waterbox", showWaterboxSetting); + SohImGui::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); + SohImGui::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); + SohImGui::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); + SohImGui::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); - ImGui::Checkbox("Apply as decal", &applyAsDecal); + SohImGui::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " "with the scene geometry, but can cause other artifacts."); - ImGui::Checkbox("Shaded", &isShaded); + SohImGui::EnhancementCheckbox("Shaded", "gColViewerShaded"); InsertHelpHoverText("Applies the scene's shading to the collision display."); // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() @@ -119,17 +79,20 @@ void DrawColViewerWindow(bool& open) { if (ImGui::TreeNode("Colors")) { InsertHelpHoverText(colorHelpText); - DrawColorPicker("Normal", sceneColor); - DrawColorPicker("Hookshot", hookshotColor); - DrawColorPicker("Entrance", entranceColor); - DrawColorPicker("Special Surface (Grass/Sand/Etc)", specialSurfaceColor); - DrawColorPicker("Interactable (Vines/Crawlspace/Etc)", interactableColor); - DrawColorPicker("Slope", slopeColor); - DrawColorPicker("Void", voidColor); - DrawColorPicker("OC", ocColor); - DrawColorPicker("AC", acColor); - DrawColorPicker("AT", atColor); - DrawColorPicker("Waterbox", waterboxColor); + SohImGui::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); + SohImGui::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), + false); + SohImGui::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); + SohImGui::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", + specialSurface_col, ImVec4(192, 255, 192, 255), false); + SohImGui::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", + interactable_col, ImVec4(192, 0, 192, 255), false); + SohImGui::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); + SohImGui::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); + SohImGui::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); + SohImGui::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); + SohImGui::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); + SohImGui::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); ImGui::TreePop(); } else { @@ -161,13 +124,12 @@ void CalcTriNorm(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, Vec3f& norm) .n = {.ob = { x, y, z }, .tc = { qs105(s), qs105(t) }, .n = { nx, ny, nz }, .a = ca } \ } - void CreateCylinderData() { constexpr int32_t CYL_DIVS = 12; cylinderGfx.reserve(5 + CYL_DIVS * 2); cylinderVtx.reserve(2 + CYL_DIVS * 2); - cylinderVtx.push_back(gdSPDefVtxN(0, 0, 0, 0, 0, 0, -127, 0, 0xFF)); // Bottom center vertex + cylinderVtx.push_back(gdSPDefVtxN(0, 0, 0, 0, 0, 0, -127, 0, 0xFF)); // Bottom center vertex cylinderVtx.push_back(gdSPDefVtxN(0, 128, 0, 0, 0, 0, 127, 0, 0xFF)); // Top center vertex // Create two rings of vertices for (int i = 0; i < CYL_DIVS; ++i) { @@ -210,9 +172,10 @@ void CreateCylinderData() { cylinderGfx.push_back(gsSPEndDisplayList()); } -// This subdivides a face into four tris by placing new verticies at the midpoints of the sides (Like a triforce!), then blowing up the -// verticies so they are on the unit sphere -void CreateSphereFace(std::vector>& faces, int32_t v0Index, int32_t v1Index, int32_t v2Index) { +// This subdivides a face into four tris by placing new verticies at the midpoints of the sides (Like a triforce!), then +// blowing up the verticies so they are on the unit sphere +void CreateSphereFace(std::vector>& faces, int32_t v0Index, int32_t v1Index, + int32_t v2Index) { size_t nextIndex = sphereVtx.size(); size_t v01Index = nextIndex; @@ -248,9 +211,9 @@ void CreateSphereFace(std::vector>& faces, in } } -// Creates a sphere following the idea in here: http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html -// Spcifically, create a icosahedron by realizing that the points can be placed on 3 rectangles that are on each unit plane. -// Then, subdividing each face. +// Creates a sphere following the idea in here: +// http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html Spcifically, create a icosahedron by +// realizing that the points can be placed on 3 rectangles that are on each unit plane. Then, subdividing each face. void CreateSphereData() { std::vector base; @@ -351,7 +314,7 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { alpha = 0xFF; } - if (applyAsDecal) { + if (CVar_GetS32("gColViewerDecal", 0) != 0) { rm |= ZMODE_DEC; } else if (setting == ColRenderSetting::Transparent) { rm |= ZMODE_XLU; @@ -363,7 +326,7 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { gfx.push_back(gsDPSetCycleType(G_CYC_1CYCLE)); gfx.push_back(gsDPSetRenderMode(rm | blc1, rm | blc2)); - if (isShaded) { + if (CVar_GetS32("gColViewerShaded", 0) != 0) { gfx.push_back(gsDPSetCombineMode(G_CC_MODULATERGB_PRIM_ENVA, G_CC_MODULATERGB_PRIM_ENVA)); gfx.push_back(gsSPLoadGeometryMode(G_CULL_BACK | G_ZBUFFER | G_LIGHTING)); } else { @@ -376,10 +339,16 @@ void InitGfx(std::vector& gfx, ColRenderSetting setting) { // Draws a dynapoly structure (scenes or Bg Actors) void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { - uint32_t color = sceneColor; - uint32_t lastColor = color; - dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF, - (color >> 0) & 0xFF)); + uint32_t colorR = CVar_GetS32("gColViewerColorNormalR", 255); + uint32_t colorG = CVar_GetS32("gColViewerColorNormalG", 255); + uint32_t colorB = CVar_GetS32("gColViewerColorNormalB", 255); + uint32_t colorA = 255; + + uint32_t lastColorR = colorR; + uint32_t lastColorG = colorG; + uint32_t lastColorB = colorB; + + dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA)); // This keeps track of if we have processed a poly, but not drawn it yet so we can batch them. // This saves several hundred commands in larger scenes @@ -389,34 +358,49 @@ void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { CollisionPoly* poly = &col->polyList[i]; if (SurfaceType_IsHookshotSurface(&gGlobalCtx->colCtx, poly, bgId)) { - color = hookshotColor; + colorR = CVar_GetS32("gColViewerColorHookshotR", 128); + colorG = CVar_GetS32("gColViewerColorHookshotG", 128); + colorB = CVar_GetS32("gColViewerColorHookshotB", 255); } else if (func_80041D94(&gGlobalCtx->colCtx, poly, bgId) > 0x01) { - color = interactableColor; + colorR = CVar_GetS32("gColViewerColorInteractableR", 192); + colorG = CVar_GetS32("gColViewerColorInteractableG", 0); + colorB = CVar_GetS32("gColViewerColorInteractableB", 192); } else if (func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x0C) { - color = voidColor; + colorR = CVar_GetS32("gColViewerColorVoidR", 255); + colorG = CVar_GetS32("gColViewerColorVoidG", 0); + colorB = CVar_GetS32("gColViewerColorVoidB", 0); } else if (SurfaceType_GetSceneExitIndex(&gGlobalCtx->colCtx, poly, bgId) || func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x05) { - color = entranceColor; + colorR = CVar_GetS32("gColViewerColorEntranceR", 0); + colorG = CVar_GetS32("gColViewerColorEntranceG", 255); + colorB = CVar_GetS32("gColViewerColorEntranceB", 0); } else if (func_80041D4C(&gGlobalCtx->colCtx, poly, bgId) != 0 || SurfaceType_IsWallDamage(&gGlobalCtx->colCtx, poly, bgId)) { - color = specialSurfaceColor; + colorR = CVar_GetS32("gColViewerColorSpecialSurfaceR", 192); + colorG = CVar_GetS32("gColViewerColorSpecialSurfaceG", 255); + colorB = CVar_GetS32("gColViewerColorSpecialSurfaceB", 192); } else if (SurfaceType_GetSlope(&gGlobalCtx->colCtx, poly, bgId) == 0x01) { - color = slopeColor; + colorR = CVar_GetS32("gColViewerColorSlopeR", 255); + colorG = CVar_GetS32("gColViewerColorSlopeG", 255); + colorB = CVar_GetS32("gColViewerColorSlopeB", 128); } else { - color = sceneColor; + colorR = CVar_GetS32("gColViewerColorNormalR", 255); + colorG = CVar_GetS32("gColViewerColorNormalG", 255); + colorB = CVar_GetS32("gColViewerColorNormalB", 255); } - if (lastColor != color) { + if (colorR != lastColorR || colorG != lastColorG || colorB != lastColorB) { // Color changed, flush previous poly if (previousPoly) { dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0)); dl.push_back(gsSP1Triangle(0, 1, 2, 0)); previousPoly = false; } - dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF, - (color >> 0) & 0xFF)); + dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA)); } - lastColor = color; + lastColorR = colorR; + lastColorG = colorG; + lastColorB = colorB; Vec3s* va = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIA)]; Vec3s* vb = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIB)]; @@ -450,7 +434,9 @@ void DrawDynapoly(std::vector& dl, CollisionHeader* col, int32_t bgId) { // Draws the scene void DrawSceneCollision() { - if (showSceneColSetting == ColRenderSetting::Disabled) { + ColRenderSetting showSceneColSetting = (ColRenderSetting)CVar_GetS32("gColViewerScene", 0); + + if (showSceneColSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) { return; } @@ -463,7 +449,8 @@ void DrawSceneCollision() { // Draws all Bg Actors void DrawBgActorCollision() { - if (showBgActorSetting == ColRenderSetting::Disabled) { + ColRenderSetting showBgActorSetting = (ColRenderSetting)CVar_GetS32("gColViewerBgActors", 0); + if (showBgActorSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) { return; } @@ -489,7 +476,6 @@ void DrawBgActorCollision() { dl.push_back(gsSPPopMatrix(G_MTX_MODELVIEW)); } } - } // Draws a quad @@ -588,7 +574,8 @@ void DrawColCheckList(std::vector& dl, Collider** objects, int32_t count) { // Draws all Col Check objects void DrawColCheckCollision() { - if (showColCheckSetting == ColRenderSetting::Disabled) { + ColRenderSetting showColCheckSetting = (ColRenderSetting)CVar_GetS32("gColViewerColCheck", 0); + if (showColCheckSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) { return; } @@ -598,16 +585,15 @@ void DrawColCheckCollision() { CollisionCheckContext& col = gGlobalCtx->colChkCtx; - dl.push_back(gsDPSetPrimColor(0, 0, (ocColor >> 24) & 0xFF, (ocColor >> 16) & 0xFF, (ocColor >> 8) & 0xFF, - (ocColor >> 0) & 0xFF)); + dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorOCR", 255), CVar_GetS32("gColViewerColorOCG", 255), + CVar_GetS32("gColViewerColorOCB", 255), 255)); DrawColCheckList(dl, col.colOC, col.colOCCount); - - dl.push_back(gsDPSetPrimColor(0, 0, (acColor >> 24) & 0xFF, (acColor >> 16) & 0xFF, (acColor >> 8) & 0xFF, - (acColor >> 0) & 0xFF)); + dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorACR", 0), CVar_GetS32("gColViewerColorACG", 0), + CVar_GetS32("gColViewerColorACB", 255), 255)); DrawColCheckList(dl, col.colAC, col.colACCount); + dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorATR", 255), CVar_GetS32("gColViewerColorATG", 0), + CVar_GetS32("gColViewerColorATB", 0), 255)); - dl.push_back(gsDPSetPrimColor(0, 0, (atColor >> 24) & 0xFF, (atColor >> 16) & 0xFF, (atColor >> 8) & 0xFF, - (atColor >> 0) & 0xFF)); DrawColCheckList(dl, col.colAT, col.colATCount); } @@ -641,15 +627,18 @@ extern "C" f32 zdWaterBoxMinY; // Draws all waterboxes void DrawWaterboxList() { - if (showWaterboxSetting == ColRenderSetting::Disabled) { + ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVar_GetS32("gColViewerWaterbox", 0); + if (showWaterboxSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) { return; } std::vector& dl = (showWaterboxSetting == ColRenderSetting::Transparent) ? xluDl : opaDl; InitGfx(dl, showWaterboxSetting); dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH)); - dl.push_back(gsDPSetPrimColor(0, 0, (waterboxColor >> 24) & 0xFF, (waterboxColor >> 16) & 0xFF, - (waterboxColor >> 8) & 0xFF, (waterboxColor >> 0) & 0xFF)); + + dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorWaterboxR", 0), + CVar_GetS32("gColViewerColorWaterboxG", 0), + CVar_GetS32("gColViewerColorWaterboxB", 255), 255)); CollisionHeader* col = gGlobalCtx->colCtx.colHeader; for (int32_t waterboxIndex = 0; waterboxIndex < col->numWaterBoxes; waterboxIndex++) { @@ -664,8 +653,7 @@ void DrawWaterboxList() { } // Resets a vector for the next frame and returns the capacity -template -size_t ResetVector(T& vec) { +template size_t ResetVector(T& vec) { size_t oldSize = vec.size(); vec.clear(); // Reserve slightly more space than last frame to account for variance (such as different amounts of bg actors)