Skip to content

feat(hud): add global HUD settings with a master toggle and per-property overrides - #1112

Open
Zgoly wants to merge 6 commits into
Polyfrost:v1from
Zgoly:v1
Open

Zgoly wants to merge 6 commits into
Polyfrost:v1from
Zgoly:v1

Conversation

@Zgoly

@Zgoly Zgoly commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Description

Adds GlobalHudSettings, holding preferences that apply to every HUD from every mod. Appearance settings pair an override switch with a value: off leaves each HUD on its own look, on routes the global value through the new effective* accessors on Hud without touching stored values.

Enabled gates drawing entirely, while the HUD editor keeps rendering so the user can get back. Values are editable under Preferences > Global HUD and from a panel in the design studio, both writing through GlobalHudSettingsBridge.

image image image

Related Issue(s)

none

Checklist

  • I made a clear description of what was changed
  • I stated why these changes were necessary
  • I updated documentation or said what needs to be updated
  • I made sure these changes are backwards compatible
  • This pull request is for one feature/bug fix

@Wyvest Wyvest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you move the button to above the hud icons (so where the old global hidden button was) with a settings icon

@Zgoly
Zgoly requested a review from Wyvest September 26, 2026 22:03
Comment on lines +238 to +242
when (val looks = t.getProp(PROVIDER_LOOKS)?.get()) {
is Array<*> -> looks.forEach { if (it != null) noteProviderLook(it.toString()) }
is Iterable<*> -> looks.forEach { if (it != null) noteProviderLook(it.toString()) }
}
hudProviders.values.forEach { applyProviderLook(it) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Reset provider looks when switching profiles

After baking overrides in profile A, switching to a blank profile B retains A's provider styles. teardownForProfile() clears knownProviders but not providerLooks, so this load reapplies stale entries and subsequent registry saves persist them into B. This reproduces with an unplaced, multi-instance HUD. Clear the cache and restore provider defaults before loading the destination profile's looks.

Comment on lines +2091 to +2092
AnimatedVisibility(
visible = globalPanelOpen && libraryChromeVisible,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Keep global controls accessible when the library is empty

When all registered HUDs are single-instance and already placed, addable and consequently modIds are empty, making libraryChromeVisible false. Both the new settings button and this panel therefore disappear despite existing HUDs needing configuration. Decouple global-control visibility from available library entries so users can still access global settings and “Apply to all HUDs” in this state.

Comment on lines +219 to +220
// providers have no tree, so their look is remembered in the registry instead
if (hud !in HudManager.activeInstances) HudManager.storeProviderLook(hud)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Persist applied looks for active single-instance providers

A single-instance HUD is also its own provider, so this condition skips saving its provider look while placed. After applying overrides, disabling them, deleting that HUD and restarting, adding it again restores the original appearance rather than the applied look; re-adding before restarting retains it. Persist the look for every registered provider, including providers also present in activeInstances, so the promised defaults for future placements survive deletion and restart.

Deftu added 2 commits October 23, 2026 22:56
# Conflicts:
#	modules/hud/api/hud.api
#	modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/HudBackgroundMerge.kt
#	modules/internal/src/main/java/org/polyfrost/oneconfig/internal/OneConfigConfig.java
#	modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/screens/HudDesignStudio.kt
#	modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/screens/sections/Designer.kt
#	modules/internal/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/screens/sections/Settings.kt
@Deftu
Deftu requested a review from lunaynx October 23, 2026 20:56
for (hud in HudManager.activeInstances) {
if (hud !is LegacyHud) continue
if (!HudManager.isEditing) {
if (!GlobalHudSettings.enabled) continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 [P2] Apply the master visibility switch to compatibility HUDs

With compatibility-wrapped HUDs such as Skyblocker widgets, disabling the HUD overlay still leaves those elements visible after exiting the editor. They implement LegacyHudMarker, not LegacyHud, so this loop skips them; HudManager also excludes them, while their original rendering hooks only check CompatOverlayRenderer.oneConfigScreenOpen(). Gate the compatibility rendering paths on the master switch too, without overwriting individual HUD visibility preferences.

Comment on lines +220 to +221
// providers have no tree, so their look is remembered in the registry instead
if (providers.any { it === hud }) HudManager.storeProviderLook(hud)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 [P2] Include provider appearance changes in undo history

After applying a global font and then undoing, HudHistory restores placed HUDs but leaves provider values and their persisted registry entries unchanged. Disabling the override and adding another HUD therefore uses the supposedly undone font, including after restarting. A targeted test reproduces this partial undo. Provider appearance changes need to participate in the same history operation as the placed HUD changes.

Comment on lines +500 to +501
key = key * 31 + (hud.effectiveBackgroundRadius * hud.effectiveScale * 4f).roundToInt()
key = key * 31 + (if (hud.effectiveShowBackground) 1 else 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 [P2] Invalidate the merge fast path when global backgrounds change

When the new public API changes background overrides outside the editor, no HUD geometryStamp changes. HudManager.updateBackgroundGroups() consequently returns through its stable fast path before evaluating this updated key. Merged backgrounds retain stale visibility or radius, and newly matching backgrounds do not merge until another geometry change occurs. Include the global background settings in the fast-path invalidation; a targeted radius-override test reproduces the stale groups.

Comment on lines +706 to +712
@SuppressWarnings("unchecked")
public static void setGlobalHudOption(String option, Object value) {
OneConfigConfig inst = INSTANCE;
if (inst == null || inst.tree == null) {
return;
}
((Property<Object>) inst.getProperty(option)).set(value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 [P3] Use the existing type-erased property setter

Property.setAs(value) already supports writing values without this unchecked cast, so the new suppression is unnecessary. Use that setter, or document why the cast is required and safe if retained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants