From 6b26aa55744a947cafb9435f67ce8b25bb537a0c Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Tue, 26 May 2026 19:05:53 -0400 Subject: [PATCH] hocclk: improve ui yes i did vibecode this, no i don't care --- .claude/settings.local.json | 10 ----- .../overlay/src/ui/elements/base_frame.h | 15 ++++--- .../overlay/src/ui/gui/app_profile_gui.cpp | 1 + .../hoc-clk/overlay/src/ui/gui/base_gui.cpp | 24 +++++++++- Source/hoc-clk/overlay/src/ui/gui/base_gui.h | 2 + .../overlay/src/ui/gui/base_menu_gui.cpp | 9 ++-- .../overlay/src/ui/gui/base_menu_gui.h | 1 + .../overlay/src/ui/gui/freq_choice_gui.cpp | 1 + .../src/ui/gui/global_override_gui.cpp | 1 + .../hoc-clk/overlay/src/ui/gui/main_gui.cpp | 8 ++++ Source/hoc-clk/overlay/src/ui/gui/main_gui.h | 2 + .../hoc-clk/overlay/src/ui/gui/misc_gui.cpp | 44 ++++++++++++------- Source/hoc-clk/overlay/src/ui/gui/ult_ext.h | 22 ++++++++++ .../overlay/src/ui/gui/value_choice_gui.cpp | 1 + 14 files changed, 101 insertions(+), 40 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 6b3eec05..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "permissions": { - "allow": [ - "PowerShell(\\(Get-Item \"c:\\\\Users\\\\sould\\\\Documents\\\\GitHub\\\\Horizon-OC\\\\Source\\\\hoc-clk\\\\assets\\\\hoc.rgba\"\\).Length)", - "PowerShell(python --version)", - "PowerShell(magick --version 2>$null)", - "PowerShell(convert --version 2>$null)" - ] - } -} diff --git a/Source/hoc-clk/overlay/src/ui/elements/base_frame.h b/Source/hoc-clk/overlay/src/ui/elements/base_frame.h index 58f6025f..be36ccef 100644 --- a/Source/hoc-clk/overlay/src/ui/elements/base_frame.h +++ b/Source/hoc-clk/overlay/src/ui/elements/base_frame.h @@ -28,20 +28,21 @@ #pragma once #include -#include "../gui/base_gui.h" + +class BaseGui; + +static constexpr u16 HOC_HEADER_HEIGHT = 287; +// Bottom edge of the drawn box: 106 + TOP_Y_OFFSET(15) + 156 = 277 +static constexpr u16 HOC_BOX_BOTTOM = 277; class BaseFrame : public tsl::elm::HeaderOverlayFrame { public: - BaseFrame(BaseGui* gui) : tsl::elm::HeaderOverlayFrame(234) { + BaseFrame(BaseGui* gui, u16 headerHeight = HOC_HEADER_HEIGHT) : tsl::elm::HeaderOverlayFrame(headerHeight) { this->gui = gui; } - void draw(tsl::gfx::Renderer* renderer) override - { - tsl::elm::HeaderOverlayFrame::draw(renderer); - this->gui->preDraw(renderer); - } + void draw(tsl::gfx::Renderer* renderer) override; protected: BaseGui* gui; diff --git a/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp index 2b1bdbea..50925d83 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp @@ -25,6 +25,7 @@ */ +#include "ult_ext.h" #include "app_profile_gui.h" #include "../format.h" diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp index ea7b7e3f..8a0a088d 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp @@ -25,9 +25,13 @@ */ #include "base_gui.h" - #include "../elements/base_frame.h" +void BaseFrame::draw(tsl::gfx::Renderer* renderer) { + tsl::elm::HeaderOverlayFrame::draw(renderer); + this->gui->preDraw(renderer); +} + #include #include @@ -142,11 +146,27 @@ void BaseGui::preDraw(tsl::gfx::Renderer* renderer) { STATIC_TEAL, false ); + + static const std::string versionStr = "Version " + getVersionString(); + static constexpr tsl::Color versionColor(9, 9, 9, 15); + static constexpr s32 vx = LOGO_TEXT_X + 15; + static constexpr s32 vy = TEXT_Y + 18; + static constexpr s32 fs = 15; + static constexpr s32 skew = 3; + static constexpr s32 passes = 10; + for (s32 i = 0; i < passes; i++) { + s32 sliceY = (vy - fs) + i * fs / passes; + s32 sliceH = fs / passes + 1; + s32 xOff = skew - (skew * i / (passes - 1)); + renderer->enableScissoring(0, sliceY, tsl::cfg::FramebufferWidth, sliceH); + renderer->drawString(versionStr.c_str(), false, vx + xOff, vy, fs, versionColor); + renderer->disableScissoring(); + } } tsl::elm::Element* BaseGui::createUI() { - BaseFrame* rootFrame = new BaseFrame(this); + BaseFrame* rootFrame = new BaseFrame(this, this->headerHeight()); rootFrame->setContent(this->baseUI()); return rootFrame; } diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_gui.h b/Source/hoc-clk/overlay/src/ui/gui/base_gui.h index eca76c09..0cae8bcd 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/base_gui.h @@ -28,6 +28,7 @@ #pragma once #include +#include "../elements/base_frame.h" #include #include #include @@ -46,6 +47,7 @@ class BaseGui : public tsl::Gui tsl::elm::Element* createUI() override; virtual tsl::elm::Element* baseUI() = 0; virtual void refresh() {} + virtual u16 headerHeight() const { return HOC_HEADER_HEIGHT; } private: }; diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp index 67f2d2e6..82835eb5 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp @@ -29,6 +29,8 @@ #include "fatal_gui.h" #include "../format.h" +#define TOP_Y_OFFSET 15 + // Cache hardware model to avoid repeated syscalls BaseMenuGui::BaseMenuGui() : tempColors{ tsl::Color(0), tsl::Color(0), tsl::Color(0), tsl::Color(0), tsl::Color(0), tsl::Color(0), tsl::Color(0), } @@ -77,10 +79,10 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { static u32 maxProfileValueWidth = renderer->getTextDimensions("USB Charger", false, SMALL_TEXT_SIZE).first; // longest word - u32 y = 91; + u32 y = 91 + TOP_Y_OFFSET; // === TOP SECTION === - renderer->drawRoundedRect(14, 70-1, 420, 30+2, 12.0f, renderer->aWithOpacity(tsl::tableBGColor)); + renderer->drawRoundedRect(14, 70-1 + TOP_Y_OFFSET, 420, 30+2, 12.0f, renderer->aWithOpacity(tsl::tableBGColor)); // App ID - use pre-formatted string renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); @@ -93,7 +95,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { y += 38; // Direct assignment instead of += 38 // === MAIN DATA SECTION === - renderer->drawRoundedRect(14, 106, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor)); + renderer->drawRoundedRect(14, 106 + TOP_Y_OFFSET, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor)); // === FREQUENCY SECTION === // Labels first (better cache locality) @@ -348,7 +350,6 @@ void BaseMenuGui::refresh() tsl::elm::Element* BaseMenuGui::baseUI() { auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CustomDrawer([](tsl::gfx::Renderer*, s32, s32, s32, s32) {}), 35); // add a bit of space this->listElement = list; this->listUI(); diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.h b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.h index 46d9c237..4554298c 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.h @@ -84,6 +84,7 @@ class BaseMenuGui : public BaseGui tsl::elm::Element* baseUI() override; void refresh() override; virtual void listUI() = 0; + u16 headerHeight() const override { return HOC_BOX_BOTTOM + 9; } private: char displayStrings[48][32]; // Pre-formatted display strings diff --git a/Source/hoc-clk/overlay/src/ui/gui/freq_choice_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/freq_choice_gui.cpp index cc1325d2..94a28d85 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/freq_choice_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/freq_choice_gui.cpp @@ -25,6 +25,7 @@ */ +#include "ult_ext.h" #include "freq_choice_gui.h" #include "../format.h" diff --git a/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp index 1bdf2ab0..197b8d53 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp @@ -16,6 +16,7 @@ * */ +#include "ult_ext.h" #include "../format.h" #include "fatal_gui.h" #include "global_override_gui.h" diff --git a/Source/hoc-clk/overlay/src/ui/gui/main_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/main_gui.cpp index 133be0f4..608a874b 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/main_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/main_gui.cpp @@ -32,6 +32,14 @@ #include "global_override_gui.h" #include "misc_gui.h" #include "about_gui.h" +#include "ult_ext.h" + +tsl::elm::Element* MainGui::baseUI() { + auto* list = new BoxClippedList(); + this->listElement = list; + this->listUI(); + return list; +} void MainGui::listUI() { diff --git a/Source/hoc-clk/overlay/src/ui/gui/main_gui.h b/Source/hoc-clk/overlay/src/ui/gui/main_gui.h index 6eae080c..fce605c9 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/main_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/main_gui.h @@ -34,6 +34,8 @@ class MainGui : public BaseMenuGui public: MainGui() {} ~MainGui() {} + tsl::elm::Element* baseUI() override; void listUI() override; void refresh() override; + u16 headerHeight() const override { return HOC_HEADER_HEIGHT - 25; } }; \ No newline at end of file diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index 746ccaea..20aa6b61 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -17,6 +17,7 @@ */ #include "misc_gui.h" +#include "ult_ext.h" #include "fatal_gui.h" #include "config_info_strings.h" #include "../format.h" @@ -547,7 +548,7 @@ void MiscGui::listUI() ValueThresholds thresholdsDisabled(0, 0); std::vector noNamedValues = {}; - this->listElement->addItem(new tsl::elm::CategoryHeader("Settings")); + this->listElement->addItem(new CompactCategoryHeader("Settings")); tsl::elm::CustomDrawer* rebootSetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { renderer->drawString("\uE150 Settings marked in blue", false, x + 20, y + 30, 18, tsl::style::color::ColorText); @@ -659,7 +660,7 @@ protected: void listUI() override { Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("General Settings")); + this->listElement->addItem(new CompactCategoryHeader("General Settings")); ValueThresholds thresholdsDisabled(0, 0); std::vector ramVoltDispModes = { @@ -719,7 +720,7 @@ protected: void listUI() override { Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("Experimental Settings")); + this->listElement->addItem(new CompactCategoryHeader("Experimental Settings")); ValueThresholds thresholdsDisabled(0, 0); if(IsMariko()) { addConfigToggle(HocClkConfigValue_MarikoMiddleFreqs, nullptr, true); @@ -855,7 +856,7 @@ protected: void listUI() override { Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("Governor Settings")); + this->listElement->addItem(new CompactCategoryHeader("Governor Settings")); ValueThresholds thresholdsDisabled(0, 0); std::vector GovernorMinHz = { @@ -896,7 +897,7 @@ protected: if(!this->context) return; - this->listElement->addItem(new tsl::elm::CategoryHeader("Display Settings")); + this->listElement->addItem(new CompactCategoryHeader("Display Settings")); addConfigToggle(HocClkConfigValue_OverwriteRefreshRate, nullptr); if(!this->context->isUsingRetroSuper) { tsl::elm::CustomDrawer* warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { @@ -951,7 +952,7 @@ protected: void listUI() override { Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("Safety Settings")); + this->listElement->addItem(new CompactCategoryHeader("Safety Settings")); addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr); addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr); addConfigToggle(HocClkConfigValue_HandheldTDP, nullptr); @@ -1011,7 +1012,7 @@ protected: - this->listElement->addItem(new tsl::elm::CategoryHeader("RAM Settings")); + this->listElement->addItem(new CompactCategoryHeader("RAM Settings")); addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift", {0xFFFFFFFCu, 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u}, @@ -1251,7 +1252,7 @@ protected: void listUI() override { Result rc = hocclkIpcGetConfigValues(this->configList); if (R_FAILED(rc)) [[unlikely]] { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("Memory Timings")); + this->listElement->addItem(new CompactCategoryHeader("Memory Timings")); addConfigTrackbar(KipConfigValue_t1_tRCD, "t1 tRCD", ValueRange(0, 7, 1)); addConfigTrackbar(KipConfigValue_t2_tRP, "t2 tRP", ValueRange(0, 7, 1)); @@ -1332,7 +1333,7 @@ protected: } ValueThresholds thresholdsDisabled(0, 0); - this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced")); + this->listElement->addItem(new CompactCategoryHeader("Advanced")); if(IsMariko()) { // tBreak / low-high timing graph (live, reads config each frame) { @@ -1483,6 +1484,13 @@ class RamLatenciesSubmenuGui : public MiscGui { public: RamLatenciesSubmenuGui() { } + tsl::elm::Element* baseUI() override { + auto* list = new TopAnchoredList(); + this->listElement = list; + this->listUI(); + return list; + } + protected: void normalizeLatencies(const HocClkConfigValue keysArr[4]) { @@ -1729,6 +1737,8 @@ protected: this->configNamedValues[thisKey] = buildNamedValues(tierIdx); }; + this->listElement->addItem(new CompactCategoryHeader("Latency Graph")); + { HocClkConfigValueList* cfgPtr = this->configList; bool mariko = IsMariko(); @@ -1764,7 +1774,7 @@ protected: const s32 gx = x + 52; const s32 gw = w - 64; const s32 gy = y + 14; - const s32 gh = 72; + const s32 gh = 54; const s32 th = gh / 3; const s32 axisY = gy + gh; @@ -1916,7 +1926,7 @@ protected: } } - s32 ly = y + h - 14; + const s32 ly = axisY + 46; renderer->drawRect(gx, ly, 14, 3, cRead); renderer->drawString("Read", false, gx + 17, ly + 5, 12, cRead); renderer->drawRect(gx + 60, ly, 14, 3, cWrite); @@ -1925,15 +1935,15 @@ protected: renderer->drawString("Same", false, gx + 142, ly + 5, 12, cMerge); } ); - graph->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 165); + graph->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 150); this->listElement->addItem(graph); } - this->listElement->addItem(new tsl::elm::CategoryHeader("Read Latency")); + this->listElement->addItem(new CompactCategoryHeader("Read Latency")); for (int i = 0; i < 4; i++) addLatencyRow(kTierLabels[i], i, kLatencyRKeys); - this->listElement->addItem(new tsl::elm::CategoryHeader("Write Latency")); + this->listElement->addItem(new CompactCategoryHeader("Write Latency")); for (int i = 0; i < 4; i++) addLatencyRow(kTierLabels[i], i, kLatencyWKeys); } @@ -1957,7 +1967,7 @@ protected: ValueThresholds eCpuClockThresholds(1785000, 2091000); ValueThresholds eCpuClockThresholdsUV(2091000, 2193000); - this->listElement->addItem(new tsl::elm::CategoryHeader("CPU Settings")); + this->listElement->addItem(new CompactCategoryHeader("CPU Settings")); if(IsMariko()) { addConfigTrackbar(KipConfigValue_marikoCpuUVLow, "CPU Low UV", ValueRange(0, 8, 1)); addConfigTrackbar(KipConfigValue_marikoCpuUVHigh, "CPU High UV", ValueRange(0, 12, 1)); @@ -2152,7 +2162,7 @@ protected: ValueThresholds thresholdsDisabled(0, 0); std::vector noNamedValues = {}; - this->listElement->addItem(new tsl::elm::CategoryHeader("GPU Settings")); + this->listElement->addItem(new CompactCategoryHeader("GPU Settings")); std::vector gpuUvConf = { NamedValue("HiOPT", 0), @@ -2363,7 +2373,7 @@ protected: return; } - this->listElement->addItem(new tsl::elm::CategoryHeader("GPU Custom Table (mV)")); + this->listElement->addItem(new CompactCategoryHeader("GPU Custom Table (mV)")); ValueThresholds MgpuVmaxThresholds(800, 850); ValueThresholds EgpuVmaxThresholds(950, 975); diff --git a/Source/hoc-clk/overlay/src/ui/gui/ult_ext.h b/Source/hoc-clk/overlay/src/ui/gui/ult_ext.h index e0b1fd4a..e248fc01 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/ult_ext.h +++ b/Source/hoc-clk/overlay/src/ui/gui/ult_ext.h @@ -17,6 +17,28 @@ #pragma once #include +#include "../elements/base_frame.h" + +class TopAnchoredList : public tsl::elm::List { +public: + TopAnchoredList() { m_hasSetInitialFocusHack = true; } +}; +class BoxClippedList : public tsl::elm::List { +public: + void draw(tsl::gfx::Renderer* renderer) override { + renderer->enableScissoring(0, HOC_BOX_BOTTOM, tsl::cfg::FramebufferWidth, tsl::cfg::FramebufferHeight - HOC_BOX_BOTTOM); + tsl::elm::List::draw(renderer); + renderer->disableScissoring(); + } +}; + +class CompactCategoryHeader : public tsl::elm::CategoryHeader { +public: + CompactCategoryHeader(const std::string& text) : tsl::elm::CategoryHeader(text) {} + void layout(u16 parentX, u16 parentY, u16 parentWidth, u16 parentHeight) override { + this->setBoundaries(this->getX(), this->getY(), this->getWidth(), 33); + } +}; class ImageElement : public tsl::elm::ListItem { private: diff --git a/Source/hoc-clk/overlay/src/ui/gui/value_choice_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/value_choice_gui.cpp index 9b8d6265..eaf4e6be 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/value_choice_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/value_choice_gui.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . * */ +#include "ult_ext.h" #include "value_choice_gui.h" #include "../format.h" #include "fatal_gui.h"