This documents the current preview apply contract, updates the project map to match the live code paths, and adds the local scratchpad issue tracking reminder to the workspace instructions.
13 KiB
Preview Update Map
This document maps how MangoTune updates the built-in live preview today:
- what uses live apply
- what falls back to restart
- what intentionally restarts
- what updates preview runtime only
- what does not touch preview at all
It also notes the main inconsistencies and the recommended direction.
Core Paths
1. Debounced config live apply
Code:
- mod.rs
refresh_live_preview_for_key(...)
Behavior:
- used for most normal config edits
- waits
180 ms - if preview is running:
- grabs current in-memory config
- calls
preview.apply_live_config(&config) - falls back to
preview.restart(&config)if live apply fails
Used by:
- most schema-backed rows in shared widgets
- most text-entry commit paths
- most color rows
- hotkey rows
- typography font changes
- many dashboard field edits through
maybe_reload_preview_for_key(...)
Intent:
- cheap, smooth preview refresh for ordinary config edits
2. Immediate config live apply
Code:
- mod.rs
apply_live_preview_now(...)
Behavior:
- if preview is running:
- cancels any pending debounced refresh
- immediately calls
preview.apply_live_config(&config) - falls back to
preview.restart(&config)if live apply fails
Used by:
- dashboard metric chips
- dashboard layout/style flag chips like:
CompactNo marginHorizontalOutline
- shared switch/toggle rows
Intent:
- immediate visual response for simple on/off interactions
3. Explicit restart
Code:
- overview.rs
- preview page
Restartbutton maybe_restart_active_preview(...)
- preview page
Behavior:
- always restarts the preview process/window
Used by:
- explicit
Restartbutton onLive Preview - Studio preview window size changes
- width
- height
Intent:
- for changes that need a fresh preview window/process
4. Preview runtime-only apply
Code:
- overview.rs
maybe_apply_studio_preview_runtime(...)
Behavior:
- does not push a MangoHud config rewrite
- updates the Studio preview runtime knobs only
Used by Live Preview runtime controls:
- scene
- studio scene
- FPS cap
- particle count
- particle size
- GPU passes
- interaction steps
- VRAM pressure
- vsync
- pause
Intent:
- update the preview workload/runtime without treating those as MangoHud config edits
5. Save/reload/apply-profile style preview apply
Code:
- window.rs
apply_preview_current_config(...)
Behavior:
- if preview is running:
- applies current in-memory config
- falls back to restart on failure
Used after bigger state changes:
- revert/discard unsaved changes
- undo-style restore of saved snapshot
- redo
- restore safety backup into state
- reset to defaults
- load config target from disk
- reload active config from disk
- profile apply/restore flows that replace current state
Intent:
- after whole-config replacement, immediately synchronize preview to the new state
Where Each UI Surface Lands
Shared Schema Widgets
Switch rows
Code:
- toggle_row.rs
build_switch_row(...)
Preview path:
apply_live_preview_now(...)
Notes:
- immediate
- dependency enable/disable logic runs first
- page may also refresh if dependent toggle state changed
Spin rows
Code:
- toggle_row.rs
build_spin_row(...)
Preview path:
refresh_live_preview_for_key(...)
Notes:
- debounced live apply
- good fit for repeated numeric scrubbing
Combo rows
Code:
- toggle_row.rs
build_combo_row(...)
Preview path:
refresh_live_preview_for_key(...)
Notes:
- debounced
Entry rows
Code:
- toggle_row.rs
build_entry_row(...)connect_entry_preview_commit(...)
Preview path:
- on focus-leave / commit:
refresh_live_preview_for_key(...)
Notes:
- avoids thrashing on every keystroke
- updates config/validation immediately
- preview waits until commit
Threshold triplet rows
Code:
- toggle_row.rs
build_int_triplet_row(...)connect_group_entry_preview_commit(...)
Preview path:
- on leaving the whole triplet group:
refresh_live_preview_for_key(...)
Notes:
- correct behavior for grouped value editing
Multi-select rows
Code:
- toggle_row.rs
build_multi_select_row(...)
Preview path:
refresh_live_preview_for_key(...)
Notes:
- debounced-ish via helper timing, but effectively immediate enough per toggle
Color Widgets
Single color rows
Code:
- color_row.rs
build_color_row(...)
Preview path:
- entry:
- commit on focus-leave via
refresh_live_preview_for_key(...)
- commit on focus-leave via
- swatch:
- immediate
refresh_live_preview_for_key(...)
- immediate
Color list / threshold palette rows
Code:
- color_row.rs
build_color_list_row(...)
Preview path:
- entry triplets:
- commit on leaving group via
refresh_live_preview_for_key(...)
- commit on leaving group via
- swatches:
- immediate
refresh_live_preview_for_key(...)
- immediate
Hotkeys
Code:
- hotkey_row.rs
apply_binding(...)
Preview path:
refresh_live_preview_for_key(...)
Notes:
- sensible
- hotkeys should not require restart
Typography Page
Code:
- typography.rs
apply_font_value(...)
Preview path:
refresh_live_preview_for_key(...)
Notes:
- this is reasonable if MangoHud live apply can accept font-path changes
- if users later report font changes only working after restart, this is one place to revisit
Dashboard
Position grid
Code:
- overview.rs
- position button click handlers
Preview path:
maybe_reload_preview_for_key(...)- delegates to
refresh_live_preview_for_key(...)
- delegates to
Scale/slider style controls
Code:
- overview.rs
- various uses of
build_scale_control(...)
- various uses of
Preview path:
- mostly
maybe_reload_preview_for_key(...)
Notes:
- width also uses live apply right now on dashboard
- that differs from Studio preview window width, which correctly restarts
- this is okay because dashboard
widthis MangoHud HUD width, not preview window size
Dashboard flag chips
Code:
- overview.rs
build_flag_toggle(...)
Preview path:
apply_live_preview_now(...)
Current examples:
CompactNo marginHorizontalOutline
Notes:
- this is now consistent with user expectation
- earlier forced restart path was removed
Dashboard metric chips
Code:
- overview.rs
build_metric_toggle(...)
Preview path:
apply_live_preview_now(...)
Notes:
- immediate
- dependency cascade logic runs first
Dashboard color controls
Code:
- overview.rs
build_color_control(...)connect_dashboard_entry_preview_commit(...)
Preview path:
- entry:
- commit on focus-leave via
maybe_reload_preview_for_key(...)
- commit on focus-leave via
- swatch:
- immediate
maybe_reload_preview_for_key(...)
- immediate
Live Preview Page
Preview config buttons
Code:
Behavior:
Startpreview.start(...)
Apply- direct
preview.apply_live_config(&config)
- direct
Restart- direct
preview.restart(&config)
- direct
Stop- direct
preview.stop()
- direct
Notes:
- this page is the canonical behavior reference
- shared helpers should behave consistently with
Apply
Studio runtime controls
Code:
- overview.rs
maybe_apply_studio_preview_runtime(...)maybe_restart_active_preview(...)
Behavior split:
- runtime-only live updates:
- scene
- studio scene
- fps cap
- particle count
- particle size
- gpu passes
- interaction steps
- vram pressure
- vsync
- pause
- restart:
- preview window width
- preview window height
Assessment:
- this split is correct
HUD Order
Code:
Preview path:
- if preview is running:
- direct
preview.apply_live_config(&config) - fallback
preview.restart(&config)
- direct
- if preview is not running:
refresh_live_preview_for_key(...)
Notes:
- this now matches the current shared immediate-apply behavior
- drag/drop was removed for now because it was causing native corruption
- row movement via buttons is stable
Window-Level Whole-State Flows
Code:
- window.rs
apply_preview_current_config(...)
Used by:
- revert/discard
- redo
- restore backup
- reset defaults
- config target switch
- reload from disk
- similar whole-state replace flows
Preview path:
- direct
apply_live_config - fallback
restart
Assessment:
- correct
- after a whole config replacement, immediate apply is the right default
Inconsistencies Found
1. Shared helpers previously disagreed with Live Preview -> Apply
Status:
- fixed
What was wrong:
- shared helpers used to refuse preview updates when
validator::is_saveable(...)was false - but the explicit
Applybutton onLive Previewdid not - this created confusing “manual Apply works, normal controls do not” behavior
Current state:
- shared helpers now match the
Applybutton behavior
2. HUD Order had its own crash-prone interaction model
Status:
- mitigated, not fully ideal
What changed:
- drag/drop removed
- explicit up/down controls now used
Assessment:
- behavior is stable now
- drag/drop can be revisited later as a separate feature
3. Some edits are commit-on-leave while others are immediate
Status:
- mostly intentional
Examples:
- entry fields wait for commit/leave
- toggles and swatches apply immediately
Assessment:
- this is good
- text editing should not hot-apply every keystroke
4. Preview runtime controls and MangoHud config controls use different paths
Status:
- intentional and correct
Assessment:
- Studio runtime controls should stay separate from MangoHud config live apply
Areas That Should Probably Stay As-Is
- shared switch rows using immediate apply
- shared spin/combo rows using debounced apply
- text entry rows using commit-on-leave
- Studio runtime controls using runtime-only apply
- Studio window size using restart
- whole-config replacement flows using immediate apply + restart fallback
Areas Worth Watching
1. Font changes
Current behavior:
- live apply
Potential issue:
- if MangoHud does not reliably rebuild fonts on live apply, these may need explicit restart semantics later
Current recommendation:
- keep live apply unless users report failures
2. Very structural layout changes
Current behavior:
- dashboard shell flags now live-apply
Assessment:
- that is the desired behavior
- only revisit if MangoHud itself proves some of these are not safely live-applicable
3. HUD Order
Current behavior:
- direct immediate apply + restart fallback
Assessment:
- correct
- no reason to special-case restart-only here
Recommended Direction
Rule 1
Use live apply by default for MangoHud config edits.
Rule 2
Use restart only when the preview window/process itself must be recreated.
Current known restart-only cases that fit this rule:
- Studio preview window width
- Studio preview window height
- explicit
Restartbutton
Rule 3
For typed text/group editors, commit preview updates on field/group exit rather than per keystroke.
Rule 4
Keep Live Preview -> Apply as the canonical behavior reference.
If a shared helper behaves differently from that button, the shared helper is probably the thing that is wrong.
Suggested Follow-Up Cleanup
These are code-cleanup ideas, not urgent bug fixes.
-
Centralize preview update intent into a small enum
DebouncedApplyImmediateApplyRestartRuntimeOnly
-
Replace direct ad hoc
preview.apply_live_config(...).or_else(restart)call sites with one shared helper- currently duplicated in:
mod.rsoverview.rshud_order.rswindow.rs
- currently duplicated in:
-
Add a short code comment near
Live Preview -> Apply- stating that it is the reference behavior shared helpers should match
-
Revisit drag-and-drop for
HUD Orderonly as a separate stability task- not as part of normal preview semantics work