From 70b4d6b5a5b27a98d9abc561bc7e679fe1895a57 Mon Sep 17 00:00:00 2001 From: "github-app[bot]" Date: Thu, 20 Aug 2026 07:29:18 -0700 Subject: [PATCH] Automated samples update --- .github/dependabot.yml | 2 +- .github/workflows/pr-summary-generate.yml | 2 +- Kits/ATGTK/imgui/imgui_atg.cpp | 167 +++++++++------------- Kits/ATGTK/imgui/imgui_atg.h | 44 +++--- 4 files changed, 88 insertions(+), 127 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2c48305b..5e5931af 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,4 +8,4 @@ updates: schedule: interval: "weekly" cooldown: - default-days: 7 + default-days: 7 \ No newline at end of file diff --git a/.github/workflows/pr-summary-generate.yml b/.github/workflows/pr-summary-generate.yml index b249f4ff..537afc89 100644 --- a/.github/workflows/pr-summary-generate.yml +++ b/.github/workflows/pr-summary-generate.yml @@ -185,4 +185,4 @@ jobs: needs: generate-summary uses: ./.github/workflows/pr-summary-eval-reusable.yml with: - pr-number: ${{ fromJSON(needs.generate-summary.outputs.pr-number) }} + pr-number: ${{ fromJSON(needs.generate-summary.outputs.pr-number) }} \ No newline at end of file diff --git a/Kits/ATGTK/imgui/imgui_atg.cpp b/Kits/ATGTK/imgui/imgui_atg.cpp index 47fe07c9..80319e54 100644 --- a/Kits/ATGTK/imgui/imgui_atg.cpp +++ b/Kits/ATGTK/imgui/imgui_atg.cpp @@ -22,6 +22,29 @@ namespace ImGuiAtg { + //-------------------------------------------------------------------------------------- + // Input helpers + //-------------------------------------------------------------------------------------- + + void HandleStandardInput() + { + if ((!ImGui::GetIO().WantTextInput && ImGui::IsKeyPressed(ImGuiKey_F2, false)) || + (ImGui::IsKeyDown(ImGuiKey_GamepadL1) && + ImGui::IsKeyDown(ImGuiKey_GamepadR1) && + ImGui::IsKeyPressed(ImGuiKey_GamepadFaceUp, false))) + { + ToggleTheme(); + } + + if (ImGui::IsKeyDown(ImGuiKey_GamepadL1) && + ImGui::IsKeyDown(ImGuiKey_GamepadR1) && + ImGui::IsKeyDown(ImGuiKey_GamepadBack) && + ImGui::IsKeyDown(ImGuiKey_GamepadStart)) + { + PostQuitMessage(0); + } + } + //-------------------------------------------------------------------------------------- // Style / Font helpers //-------------------------------------------------------------------------------------- @@ -227,14 +250,14 @@ namespace ImGuiAtg // Fullscreen layout -- a single borderless window filling the framebuffer. //-------------------------------------------------------------------------------------- - void BeginFullscreenLayout(std::optional titleSafe) + void BeginFullscreenLayout() { // Resolve the title-safe choice: explicit caller value wins, otherwise default // to "on" for console builds and "off" for PC. #ifdef _GAMING_XBOX - const bool applyTitleSafe = titleSafe.value_or(true); + const bool applyTitleSafe = true; #else - const bool applyTitleSafe = titleSafe.value_or(false); + const bool applyTitleSafe = false; #endif ImVec2 displaySize = ImGui::GetIO().DisplaySize; @@ -276,6 +299,12 @@ namespace ImGuiAtg } void DrawFooter() + { + BeginFooter(); + EndFooter(); + } + + void BeginFooter() { // Collapse vertical spacing so the footer takes the minimum height possible const ImVec2 spacing = ImGui::GetStyle().ItemSpacing; @@ -283,82 +312,34 @@ namespace ImGuiAtg ImGui::Separator(); - // Exit hint -- click to quit. ControllerText wraps its output in a Group, - // so the IsItem* queries here apply to the entire glyph+text run. - ControllerText("[Alt]+[F4] / [LB]+[RB]+[View]+[Menu] Exit"); - if (ImGui::IsItemHovered()) - { - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - PostQuitMessage(0); - } - - ImGui::SameLine(0, Scaled(80.0f)); + // Exit hint -- click to quit. + if (FooterItem("[Alt]+[F4] / [LB]+[RB]+[View]+[Menu] Exit")) + PostQuitMessage(0); // Theme toggle hint -- click to flip light/dark. - ControllerText("[F2] / [LB]+[RB]+[Y] Toggle Light/Dark"); + if (FooterItem("[F2] / [LB]+[RB]+[Y] Toggle Light/Dark")) + ToggleTheme(); + + // Cursor is left on the footer line. A sample may append its own hints here + // with FooterItem() before calling EndFooter(). + } + + bool FooterItem(const char* text) + { + ControllerText(text); + ImGui::SameLine(0, Scaled(80.0f)); if (ImGui::IsItemHovered()) { ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) - ToggleTheme(); + return true; } - - ImGui::PopStyleVar(); + return false; } - void HandleStandardInput() + void EndFooter() { - // Theme toggle. Exit via Alt+F4 is handled by Windows (DefWindowProc), so we - // only wire up F2 here. Suppressed while ImGui is capturing keyboard input - // for a text widget so typing in a text box doesn't flip the theme. - if (!ImGui::GetIO().WantTextInput) - { - if (ImGui::IsKeyPressed(ImGuiKey_F2, false)) - ToggleTheme(); - } - - using Microsoft::WRL::ComPtr; - static ComPtr s_gameInput; - static GameInputGamepadState s_prevGamepadState{}; - - if (!s_gameInput) - { - if (FAILED(::GameInputCreate(&s_gameInput))) - return; - } - - ComPtr<::IGameInputReading> reading; - if (FAILED(s_gameInput->GetCurrentReading(::GameInputKindGamepad, nullptr, &reading))) - return; - - ::GameInputGamepadState curr{}; - if (!reading->GetGamepadState(&curr)) - return; - - const auto buttons = curr.buttons; - const auto prevButtons = s_prevGamepadState.buttons; - - // Exit combo: LB + RB + View + Menu - if ((buttons & ::GameInputGamepadLeftShoulder) && - (buttons & ::GameInputGamepadRightShoulder) && - (buttons & ::GameInputGamepadMenu) && - (buttons & ::GameInputGamepadView)) - { - PostQuitMessage(0); - } - - // Theme toggle combo: LB + RB + Y (edge-triggered to fire once per press) - const bool themeCombo = (buttons & ::GameInputGamepadLeftShoulder) && - (buttons & ::GameInputGamepadRightShoulder) && - (buttons & ::GameInputGamepadY); - const bool wasThemeCombo = (prevButtons & ::GameInputGamepadLeftShoulder) && - (prevButtons & ::GameInputGamepadRightShoulder) && - (prevButtons & ::GameInputGamepadY); - if (themeCombo && !wasThemeCombo) - ToggleTheme(); - - s_prevGamepadState = curr; + ImGui::PopStyleVar(); } //-------------------------------------------------------------------------------------- @@ -458,26 +439,6 @@ namespace ImGuiAtg // Controller string -- mixed text and glyph font rendering //-------------------------------------------------------------------------------------- - // Encode a Unicode codepoint (BMP) to a 4-byte UTF-8 buffer. Returns length written. - static int EncodeUtf8(uint32_t cp, char* buf) - { - if (cp < 0x80) - { - buf[0] = static_cast(cp); - return 1; - } - if (cp < 0x800) - { - buf[0] = static_cast(0xC0 | (cp >> 6)); - buf[1] = static_cast(0x80 | (cp & 0x3F)); - return 2; - } - buf[0] = static_cast(0xE0 | (cp >> 12)); - buf[1] = static_cast(0x80 | ((cp >> 6) & 0x3F)); - buf[2] = static_cast(0x80 | (cp & 0x3F)); - return 3; - } - // Case-insensitive comparator for glyph tag lookup struct CaseInsensitiveLess { @@ -708,8 +669,8 @@ namespace ImGuiAtg { if (!first) ImGui::SameLine(0.0f, 0.0f); ImGui::SetCursorPosY(rowY); - char utf8[4]; - int len = EncodeUtf8(static_cast(glyph), utf8); + char utf8[5]; + int len = ImTextCharToUtf8(utf8, static_cast(glyph)); ImGui::PushFont(glyphFont, glyphSizeBase); // base size; ImGui scales by FontScaleDpi ImGui::TextUnformatted(utf8, utf8 + len); ImGui::PopFont(); @@ -736,21 +697,27 @@ namespace ImGuiAtg ImFont* glyphFont = s_glyphFont; if (static_cast(glyph) != 0 && glyphFont) { - char utf8[4]; - int len = EncodeUtf8(static_cast(glyph), utf8); + char utf8[5]; + int len = ImTextCharToUtf8(utf8, static_cast(glyph)); ImGui::PushFont(glyphFont, size); ImGui::TextUnformatted(utf8, utf8 + len); ImGui::PopFont(); } else if (fallback) { - // Vertically center fallback text within the glyph-sized row - float textHeight = ImGui::GetFontSize(); - float rowHeight = size * GetCurrentScale(); - float offsetY = (rowHeight - textHeight) * 0.5f; - if (offsetY > 0.0f) - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + offsetY); - ImGui::TextUnformatted(fallback); + // Vertically center fallback text within the glyph-sized row. The item must + // reserve the full row height (like a real glyph) so it aligns consistently + // whether or not a glyph precedes it on the line -- otherwise the first item + // on an all-fallback row sits higher than its SameLine siblings. We draw the + // text manually at the centered offset and reserve the height with a Dummy. + const float textHeight = ImGui::GetFontSize(); + const float rowHeight = ImMax(size * GetCurrentScale(), textHeight); + const float offsetY = (rowHeight - textHeight) * 0.5f; + const ImVec2 pos = ImGui::GetCursorScreenPos(); + const ImVec2 textSize = ImGui::CalcTextSize(fallback); + ImGui::GetWindowDrawList()->AddText(ImVec2(pos.x, pos.y + offsetY), + ImGui::GetColorU32(ImGuiCol_Text), fallback); + ImGui::Dummy(ImVec2(textSize.x, rowHeight)); } } diff --git a/Kits/ATGTK/imgui/imgui_atg.h b/Kits/ATGTK/imgui/imgui_atg.h index acd56875..44d337d9 100644 --- a/Kits/ATGTK/imgui/imgui_atg.h +++ b/Kits/ATGTK/imgui/imgui_atg.h @@ -48,24 +48,12 @@ namespace ImGuiAtg // Use for fixed widget sizes: ImGuiAtg::Scaled(180) instead of 180 * scale. inline float Scaled(float value) { return value * GetCurrentScale(); } - // Full-screen layout -- creates a single borderless ImGui window filling the framebuffer. - // - // titleSafe controls the TV title-safe inset (a 5%-per-edge margin that protects - // content from being cropped by TV overscan): - // std::nullopt (default) -- automatic: enabled on Xbox console builds (_GAMING_XBOX), - // disabled on PC builds. - // true -- force the inset on, regardless of platform. - // false -- force the inset off, regardless of platform. - void BeginFullscreenLayout(std::optional titleSafe = std::nullopt); + // Full-screen layout -- creates a single borderless ImGui window filling the framebuffer, title-safe on console + void BeginFullscreenLayout(); void EndFullscreenLayout(); - // Standard sample footer -- a single-line strip with exit and theme toggle hints: - // [Alt]+[F4] / [LB]+[RB]+[View]+[Menu] Exit [F2] / [LB]+[RB]+[Y] Toggle Light/Dark - // - // DrawFooter() renders the visual footer only. The matching keyboard/gamepad - // shortcuts are processed by ImGuiAtg::HandleStandardInput(), which the sample - // Main.cpp calls automatically once per frame. - // + // Standard sample footer -- a single-line strip with exit and theme toggle hints + // // Use GetFooterHeight() to reserve space when laying out scrollable content above // the footer, e.g.: // ImGui::BeginChild("##Content", ImVec2(0, ImGui::GetContentRegionAvail().y - ImGuiAtg::GetFooterHeight())); @@ -73,21 +61,27 @@ namespace ImGuiAtg // ImGui::EndChild(); // ImGuiAtg::DrawFooter(); float GetFooterHeight(); + + // DrawFooter() renders the standard footer with no custom items. Equivalent to + // calling BeginFooter() immediately followed by EndFooter(). void DrawFooter(); + // BeginFooter()/EndFooter() let a sample append its own hints after the standard + // ones. Example: + // ImGuiAtg::BeginFooter(); + // if (ImGuiAtg::FooterItem("[F5] Reset")) + // Reset(); + // ImGuiAtg::EndFooter(); + void BeginFooter(); + void EndFooter(); + + // FooterItem() renders one footer hint between BeginFooter() and EndFooter(). + bool FooterItem(const char* text); + // Handles standard sample input -- the same shortcuts that DrawFooter() advertises: // // Alt+F4 / LB+RB+View+Menu -- exit the app (Alt+F4 is handled by Windows) // F2 / LB+RB+Y -- toggle light/dark theme - // - // Call once per frame from the main loop between ImGui::NewFrame() and Render - // (the sample Main.cpp does this for you). Maintains its own previous-frame - // gamepad state for edge detection. Keyboard shortcuts are suppressed while - // ImGui is capturing keyboard input for a text widget. Gamepad handling uses - // the v0 GameInput API (always available via the Windows SDK or the - // Microsoft.GameInput NuGet package) so this works in any sample regardless of - // which GameInput API version the sample itself targets. The kit creates its - // own IGameInput instance on first use. void HandleStandardInput(); // Splitter -- splits the current region into two resizable panels.