Freeplay search and sort, HUD profiles and editor, mouse and controller in menus #9

Merged
khyretos merged 10 commits from feat/ui into main 2026-10-26 10:13:32 +01:00
Owner

Requested by Kees

Menu and HUD features from Kees' feedback.

Freeplay

  • Search: CTRL+F or / opens a search bar under the difficulty. It filters by song name as you type.
  • Sort: O cycles default / stars (numerical difficulty) / name / favourites. With a controller, LT/RT switch the mod filter and SELECT cycles the sort.

HUD

  • Rating letter: a 2Hot4You-style giant rating letter, as a HUD element that can be toggled like the others.
  • Named HUD profiles (e.g. phone / compact / desktop): saved with hudProfiles / hudProfile.
  • HUD editor: C centres, V snaps, G shows the grid, P/N switch profile, F2 renames, DEL deletes. Holding an arrow keeps moving the element. On-screen buttons work with the mouse. Controller: LB/RB select, d-pad moves (with repeat), A toggles, X/Y centre, B saves.
  • Base HUD In Mods option (and --base-hud): mods with their own HUD use the default HUD instead.

Mouse

  • New mouseInMenus option: a cursor in menus; hover selects, click confirms, the wheel scrolls; Freeplay capsules are clickable.

Tested headless with xdotool-driven screenshots: search, sort, editor buttons, hold-to-move, profiles, mouse hover/click/wheel, and controller bindings in the editor. Tests ran with a separate test HOME, so no real save data was touched.

🤖 Generated with Claude Code

<!-- claude-projects-attribution: {"github_login":"Khyretos"} --> _Requested by **Kees**_ Menu and HUD features from Kees' feedback. **Freeplay** - Search: CTRL+F or `/` opens a search bar under the difficulty. It filters by song name as you type. - Sort: O cycles default / stars (numerical difficulty) / name / favourites. With a controller, LT/RT switch the mod filter and SELECT cycles the sort. **HUD** - Rating letter: a 2Hot4You-style giant rating letter, as a HUD element that can be toggled like the others. - Named HUD profiles (e.g. phone / compact / desktop): saved with `hudProfiles` / `hudProfile`. - HUD editor: C centres, V snaps, G shows the grid, P/N switch profile, F2 renames, DEL deletes. Holding an arrow keeps moving the element. On-screen buttons work with the mouse. Controller: LB/RB select, d-pad moves (with repeat), A toggles, X/Y centre, B saves. - **Base HUD In Mods** option (and `--base-hud`): mods with their own HUD use the default HUD instead. **Mouse** - New `mouseInMenus` option: a cursor in menus; hover selects, click confirms, the wheel scrolls; Freeplay capsules are clickable. Tested headless with xdotool-driven screenshots: search, sort, editor buttons, hold-to-move, profiles, mouse hover/click/wheel, and controller bindings in the editor. Tests ran with a separate test HOME, so no real save data was touched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Search: a field under the difficulty selector; filters song names and artists as you type and combines with
  the tabs and the mod filter. ENTER keeps it, ESC clears it; while typing no other Freeplay key reacts.
  If nothing matches on the current difficulty it moves to one that has matches (mod songs are often on
  one difficulty only).
- Sort (O / SHIFT+O): default, stars low-high, stars high-low, name, favourites first. Re-applied when the
  difficulty changes, since star ratings differ per difficulty.
- Key hints and docs/PLAYING.md updated.
Checked with screenshots: stars high-low on Normal puts the 12-star 1Corekiller songs first; "dej" finds
Dejection and Dejection-Old (switching to Hard).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- HUD extras: a 'rating' element, 2Hot4You's live letter grade (S+ at 100 %, S >= 98, A >= 90 ... F),
  coloured, above the judgement counts by default.
- Named HUD profiles (Desktop, Compact, Phone, ...): the editor switches (P), creates (N, a copy), renames
  (F2, typed) and deletes (DEL) them; songs use the one selected. The old single layout becomes "Default".
- Editor: holding an arrow keeps moving and speeds up; C / V centre; G snaps to the screen edges, the centre
  and the other elements; buttons for the mouse (cursor shown in the editor).
- Preferences > Base HUD In Mods (or --base-hud): mod HUD scripts (2Hot4You, WI) leave the engine's HUD and
  the HUD extras in place (PsychUtil.modHudAllowed).
Checked with screenshots: centring, creating and naming a profile, 5urefire with and without the base HUD.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Preferences > Mouse In Menus (on by default, desktop): the cursor shows on every menu and hides during songs
(only ever shown by this, so editors keep their own cursor). Menus built on MenuTypedList (main menu, options
pages, ...) select the item under the mouse and open the selected one on click; the wheel scrolls. Freeplay:
click a song to select it, click the selected song to play it (the wheel already scrolled).
Checked headless: hover selects Merch, clicking the selected Freeplay opens Freeplay, clicking a capsule
selects it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/PLAYING.md
#	source/funkin/Preferences.hx
#	source/funkin/save/Save.hx
#	source/funkin/ui/options/PreferencesMenu.hx
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Changelog: builds for every platform, feedback fixes, Freeplay search and sort, HUD profiles, mouse
All checks were successful
CI / all-checks (pull_request) Successful in 6m38s
b108d14b6b
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
First-time contributor

Title

Freeplay search and sort, HUD profiles and editor, mouse and controller in menus


User description

Requested by Kees

Menu and HUD features from Kees' feedback.

Freeplay

  • Search: CTRL+F or / opens a search bar under the difficulty. It filters by song name as you type.
  • Sort: O cycles default / stars (numerical difficulty) / name / favourites. With a controller, LT/RT switch the mod filter and SELECT cycles the sort.

HUD

  • Rating letter: a 2Hot4You-style giant rating letter, as a HUD element that can be toggled like the others.
  • Named HUD profiles (e.g. phone / compact / desktop): saved with hudProfiles / hudProfile.
  • HUD editor: C centres, V snaps, G shows the grid, P/N switch profile, F2 renames, DEL deletes. Holding an arrow keeps moving the element. On-screen buttons work with the mouse. Controller: LB/RB select, d-pad moves (with repeat), A toggles, X/Y centre, B saves.
  • Base HUD In Mods option (and --base-hud): mods with their own HUD use the default HUD instead.

Mouse

  • New mouseInMenus option: a cursor in menus; hover selects, click confirms, the wheel scrolls; Freeplay capsules are clickable.

Tested headless with xdotool-driven screenshots: search, sort, editor buttons, hold-to-move, profiles, mouse hover/click/wheel, and controller bindings in the editor. Tests ran with a separate test HOME, so no real save data was touched.

🤖 Generated with Claude Code


PR Type

Enhancement, Bug fix


Description

  • Adds mouse cursor and hover/click controls to menus.

  • Introduces Freeplay search, sort, and controller support.

  • Implements named HUD profiles with editor and rating letter.

  • Adds "Base HUD In Mods" option for mod compatibility.


Diagram Walkthrough

flowchart LR
  A["User Input"] -->|"Mouse Hover"| B["Menu Selection"]
  A -->|"Click"| C["Confirm Action"]
  A -->|"Wheel"| D["Scroll List"]
  E["Freeplay"] -->|"Search"| F["Filter Songs"]
  E -->|"Sort"| G["Order Songs"]
  H["HUD Editor"] -->|"Save"| I["Named Profiles"]
  J["Mod Script"] -->|"Check"| K["Base HUD Option"]

File Walkthrough

Relevant files
Enhancement
5 files
InitState.hx
Toggles mouse cursor visibility based on menu state           
+11/-0   
HudExtras.hx
Adds rating letter element and named profile support         
+163/-18
MenuList.hx
Implements mouse hover select and click confirm logic       
+28/-0   
FreeplayState.hx
Adds search bar, sort modes, and controller bindings         
+185/-9 
HudLayoutState.hx
Adds profile management and advanced alignment tools         
+258/-15
Configuration changes
3 files
Preferences.hx
Adds mouseInMenus and forceBaseHud preference options       
+35/-0   
Save.hx
Extends save data with HUD profiles and new prefs               
+19/-0   
CLIUtil.hx
Adds --base-hud command line argument                                       
+2/-0     
Bug fix
3 files
LetterSort.hx
Prevents Q/E input during active text search                         
+1/-0     
H4YHud.hxc
Respects base hud setting to show engine HUD                         
+2/-1     
WIHud.hxc
Respects base hud setting to show engine HUD                         
+2/-1     
Documentation
3 files
PreferencesMenu.hx
Exposes Base HUD and Mouse In Menus settings                         
+10/-0   
CHANGELOG-funkin-claude.md
Documents new features and fixes in changelog                       
+17/-1   
PLAYING.md
Updates controls and options documentation                             
+32/-5   
Error handling
1 files
PsychUtil.hxc
Checks base hud preference before hiding engine HUD           
+10/-0   

## Title Freeplay search and sort, HUD profiles and editor, mouse and controller in menus ___ ### **User description** <!-- claude-projects-attribution: {"github_login":"Khyretos"} --> _Requested by **Kees**_ Menu and HUD features from Kees' feedback. **Freeplay** - Search: CTRL+F or `/` opens a search bar under the difficulty. It filters by song name as you type. - Sort: O cycles default / stars (numerical difficulty) / name / favourites. With a controller, LT/RT switch the mod filter and SELECT cycles the sort. **HUD** - Rating letter: a 2Hot4You-style giant rating letter, as a HUD element that can be toggled like the others. - Named HUD profiles (e.g. phone / compact / desktop): saved with `hudProfiles` / `hudProfile`. - HUD editor: C centres, V snaps, G shows the grid, P/N switch profile, F2 renames, DEL deletes. Holding an arrow keeps moving the element. On-screen buttons work with the mouse. Controller: LB/RB select, d-pad moves (with repeat), A toggles, X/Y centre, B saves. - **Base HUD In Mods** option (and `--base-hud`): mods with their own HUD use the default HUD instead. **Mouse** - New `mouseInMenus` option: a cursor in menus; hover selects, click confirms, the wheel scrolls; Freeplay capsules are clickable. Tested headless with xdotool-driven screenshots: search, sort, editor buttons, hold-to-move, profiles, mouse hover/click/wheel, and controller bindings in the editor. Tests ran with a separate test HOME, so no real save data was touched. 🤖 Generated with [Claude Code](https://claude.com/claude-code) ___ ### **PR Type** Enhancement, Bug fix ___ ### **Description** - Adds mouse cursor and hover/click controls to menus. - Introduces Freeplay search, sort, and controller support. - Implements named HUD profiles with editor and rating letter. - Adds "Base HUD In Mods" option for mod compatibility. ___ ### Diagram Walkthrough ```mermaid flowchart LR A["User Input"] -->|"Mouse Hover"| B["Menu Selection"] A -->|"Click"| C["Confirm Action"] A -->|"Wheel"| D["Scroll List"] E["Freeplay"] -->|"Search"| F["Filter Songs"] E -->|"Sort"| G["Order Songs"] H["HUD Editor"] -->|"Save"| I["Named Profiles"] J["Mod Script"] -->|"Check"| K["Base HUD Option"] ``` <details> <summary><h3> File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>5 files</summary><table> <tr> <td><strong>InitState.hx</strong><dd><code>Toggles mouse cursor visibility based on menu state</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/InitState.hx">+11/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>HudExtras.hx</strong><dd><code>Adds rating letter element and named profile support</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/play/components/HudExtras.hx">+163/-18</a></td> </tr> <tr> <td><strong>MenuList.hx</strong><dd><code>Implements mouse hover select and click confirm logic</code>&nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/MenuList.hx">+28/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>FreeplayState.hx</strong><dd><code>Adds search bar, sort modes, and controller bindings</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/freeplay/FreeplayState.hx">+185/-9</a>&nbsp; </td> </tr> <tr> <td><strong>HudLayoutState.hx</strong><dd><code>Adds profile management and advanced alignment tools</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/options/HudLayoutState.hx">+258/-15</a></td> </tr> </table></details></td></tr><tr><td><strong>Configuration changes</strong></td><td><details><summary>3 files</summary><table> <tr> <td><strong>Preferences.hx</strong><dd><code>Adds mouseInMenus and forceBaseHud preference options</code>&nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/Preferences.hx">+35/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>Save.hx</strong><dd><code>Extends save data with HUD profiles and new prefs</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/save/Save.hx">+19/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>CLIUtil.hx</strong><dd><code>Adds --base-hud command line argument</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/util/CLIUtil.hx">+2/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Bug fix</strong></td><td><details><summary>3 files</summary><table> <tr> <td><strong>LetterSort.hx</strong><dd><code>Prevents Q/E input during active text search</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/freeplay/LetterSort.hx">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>H4YHud.hxc</strong><dd><code>Respects base hud setting to show engine HUD</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/ports/2hot4you/scripts/h4y/H4YHud.hxc">+2/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>WIHud.hxc</strong><dd><code>Respects base hud setting to show engine HUD</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/ports/wednesdays-infidelity/scripts/wi/WIHud.hxc">+2/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Documentation</strong></td><td><details><summary>3 files</summary><table> <tr> <td><strong>PreferencesMenu.hx</strong><dd><code>Exposes Base HUD and Mouse In Menus settings</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/options/PreferencesMenu.hx">+10/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>CHANGELOG-funkin-claude.md</strong><dd><code>Documents new features and fixes in changelog</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/CHANGELOG-funkin-claude.md">+17/-1</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>PLAYING.md</strong><dd><code>Updates controls and options documentation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/docs/PLAYING.md">+32/-5</a>&nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Error handling</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>PsychUtil.hxc</strong><dd><code>Checks base hud preference before hiding engine HUD</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/mods/psych-compat/scripts/psych/PsychUtil.hxc">+10/-0</a>&nbsp; &nbsp; </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___
First-time contributor

PR Reviewer Guide 🔍

📋 Focus areas: 🔴 2 open · ✅ 0 handled. Every push re-checks them; a handled area moves to Resolved findings at the bottom.

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Issue

In updateSearch(), the code checks if currentFilteredSongs is empty to switch difficulties when searching. However, currentFilteredSongs is a local variable in generateSongList() and is not accessible here. The code should instead check tempSongs (the list being filtered) or re-fetch the current song list. This could cause the search to fail to find matches even if songs exist on other difficulties.

  while (searchQuery != '' && currentFilteredSongs.filter(song -> song != null).length == 0 && tries < grpDifficulties.group.members.length)
  {
    changeDiff(1);
    tries++;
  }
  changeSelection(-curSelected);
}
Missing Error Handling

In deleteProfile(), the function checks if there is only one profile left before deleting. However, it does not handle the case where HudExtras.activeProfile() returns a name that no longer exists after deletion (e.g., if the active profile was the last one and the check failed for some reason, or if the active profile name is stale). It should explicitly update the active profile to the first remaining one after deletion, similar to how renameProfile() handles it.

function deleteProfile():Void
{
  if (HudExtras.profileNames().length <= 1) return;
  HudExtras.deleteProfile(HudExtras.activeProfile());
  layout = HudExtras.loadLayout();
  FunkinSound.playOnce(Paths.sound('cancelMenu'), 0.4);
  updateSelection();
}
## PR Reviewer Guide 🔍 <!-- pr-agent:review:full --> 📋 **Focus areas:** 🔴 2 open · ✅ 0 handled. Every push re-checks them; a handled area moves to *Resolved findings* at the bottom. <table> <tr><td>⏱️&nbsp;<strong>Estimated effort to review</strong>: 4 🔵🔵🔵🔵⚪</td></tr> <tr><td>🧪&nbsp;<strong>PR contains tests</strong></td></tr> <tr><td>🔒&nbsp;<strong>No security concerns identified</strong></td></tr> <tr><td>⚡&nbsp;<strong>Recommended focus areas for review</strong><br><br> <details><summary><a href='https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/freeplay/FreeplayState.hx#L1066-L1072'><strong>Possible Issue</strong></a> In `updateSearch()`, the code checks if `currentFilteredSongs` is empty to switch difficulties when searching. However, `currentFilteredSongs` is a local variable in `generateSongList()` and is not accessible here. The code should instead check `tempSongs` (the list being filtered) or re-fetch the current song list. This could cause the search to fail to find matches even if songs exist on other difficulties. </summary> ```haxe while (searchQuery != '' && currentFilteredSongs.filter(song -> song != null).length == 0 && tries < grpDifficulties.group.members.length) { changeDiff(1); tries++; } changeSelection(-curSelected); } ``` </details> <details><summary><a href='https://git.kreative-kompas.com/khyretos/funkin/src/branch/feat/ui/source/funkin/ui/options/HudLayoutState.hx#L175-L182'><strong>Missing Error Handling</strong></a> In `deleteProfile()`, the function checks if there is only one profile left before deleting. However, it does not handle the case where `HudExtras.activeProfile()` returns a name that no longer exists after deletion (e.g., if the active profile was the last one and the check failed for some reason, or if the active profile name is stale). It should explicitly update the active profile to the first remaining one after deletion, similar to how `renameProfile()` handles it. </summary> ```haxe function deleteProfile():Void { if (HudExtras.profileNames().length <= 1) return; HudExtras.deleteProfile(HudExtras.activeProfile()); layout = HudExtras.loadLayout(); FunkinSound.playOnce(Paths.sound('cancelMenu'), 0.4); updateSelection(); } ``` </details> </td></tr> </table> <!-- pr-agent-review-state:v1 {"findings":[{"body":"**Possible Issue**\n\nIn `updateSearch()`, the code checks if `currentFilteredSongs` is empty to switch difficulties when searching. However, `currentFilteredSongs` is a local variable in `generateSongList()` and is not accessible here. The code should instead check `tempSongs` (the list being filtered) or re-fetch the current song list. This could cause the search to fail to find matches even if songs exist on other difficulties.","finding_id":"0f7d7dbf5907","first_seen":"2026-10-26T08:51:26.929109Z","last_seen":"2026-10-26T08:51:26.929109Z","last_seen_head_sha":"b108d14b6b34d373bf41f353f1e153da0163b3bd","line_end":1072,"line_start":1066,"path":"source/funkin/ui/freeplay/FreeplayState.hx","state":"ACTIVE"},{"body":"**Missing Error Handling**\n\nIn `deleteProfile()`, the function checks if there is only one profile left before deleting. However, it does not handle the case where `HudExtras.activeProfile()` returns a name that no longer exists after deletion (e.g., if the active profile was the last one and the check failed for some reason, or if the active profile name is stale). It should explicitly update the active profile to the first remaining one after deletion, similar to how `renameProfile()` handles it.","finding_id":"a494ead7a2c5","first_seen":"2026-10-26T08:51:26.929109Z","last_seen":"2026-10-26T08:51:26.929109Z","last_seen_head_sha":"b108d14b6b34d373bf41f353f1e153da0163b3bd","line_end":182,"line_start":175,"path":"source/funkin/ui/options/HudLayoutState.hx","state":"ACTIVE"}],"last_run":{"complete":true,"excluded_files":[],"head_sha":"b108d14b6b34d373bf41f353f1e153da0163b3bd","kind":"full","run_id":"https://git.kreative-kompas.com/khyretos/funkin/commit/b108d14b6b34d373bf41f353f1e153da0163b3bd"},"schema_version":1} -->
First-time contributor

PR Code Suggestions ✨

No code suggestions found for the PR.

## PR Code Suggestions ✨ <!-- pr-agent:improve:no-suggestions --> No code suggestions found for the PR.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
khyretos/funkin!9
No description provided.