From dadf9d88d41abbf73aa86a20252c6b226aaea18c Mon Sep 17 00:00:00 2001 From: MelekTaus Moribundus Date: Sun, 28 Jun 2026 14:21:03 +0200 Subject: [PATCH] Fix paint HUD settings not persisting until a panel is dragged The debounced auto-save compared painter values against the on-disk baseline, so after any slider/toggle change the values stayed different every frame and the 0.5s timer was pushed forward endlessly, never firing. Saving only happened via the direct drag-end path. Compare against the previous-frame snapshot instead so the timer fires once the values settle. Also pin hudSaveId to a stable key so the layout is shared across scenes instead of split per-scene. Co-Authored-By: Claude Opus 4.8 --- Assets/Scenes/Main.unity | 2 +- Assets/Scripts/PaintHud.Persistence.cs | 27 +++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index df67071..87e014c 100644 --- a/Assets/Scenes/Main.unity +++ b/Assets/Scenes/Main.unity @@ -2057,7 +2057,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Assembly-CSharp::PaintHud persistHud: 1 - hudSaveId: + hudSaveId: PaintHUD modeManager: {fileID: 0} painter: {fileID: 0} layoutPrefab: {fileID: 3563111358790320208, guid: fa9dc2ea9e2c9ac4f815f666014804c8, type: 3} diff --git a/Assets/Scripts/PaintHud.Persistence.cs b/Assets/Scripts/PaintHud.Persistence.cs index e03bb50..e66d565 100644 --- a/Assets/Scripts/PaintHud.Persistence.cs +++ b/Assets/Scripts/PaintHud.Persistence.cs @@ -39,7 +39,8 @@ public partial class PaintHud // fire every frame while dragged - we push the due time forward and write once they settle. No // teardown save, so persistence never depends on a clean quit. private const float HudSaveDebounce = 0.5f; - private readonly HudValues _savedValues = new HudValues(); // mirror of what is currently on disk + private readonly HudValues _savedValues = new HudValues(); // mirror of what is currently on disk + private readonly HudValues _lastSeenValues = new HudValues(); // painter values observed last frame (settle detection) private bool _hasSavedBaseline; private bool _hudSavePending; private float _hudSaveDueTime; @@ -183,12 +184,20 @@ public partial class PaintHud // so it is immune to the destroy-pending timing of the despawn. CaptureCarry(); - // A brush-value edit differs from what is on disk -> schedule a coalesced save. Sliders fire - // every frame while dragged, so we keep pushing the due time forward and write once they settle. - if (persistHud && _hasSavedBaseline && !ValuesEqual(painter, _savedValues)) + // Debounced auto-save: (re)arm the settle timer only on frames where a value actually CHANGED + // since the last frame - not merely differs from disk. Sliders fire every frame while dragged, + // so this keeps the deadline ahead of the drag and writes once the values stop moving. Comparing + // against the on-disk baseline instead would push the deadline forward forever (the edit always + // differs from disk until it is written), so the save would never fire on its own - it only + // landed when something else, e.g. a panel drop, wrote the state directly. + if (persistHud && _hasSavedBaseline && !ValuesEqual(painter, _lastSeenValues)) { - _hudSavePending = true; - _hudSaveDueTime = Time.unscaledTime + HudSaveDebounce; + CopyValues(painter, _lastSeenValues); + if (!ValuesEqual(painter, _savedValues)) + { + _hudSavePending = true; + _hudSaveDueTime = Time.unscaledTime + HudSaveDebounce; + } } } @@ -199,7 +208,11 @@ public partial class PaintHud /// Marks the current brush values as the on-disk baseline so auto-save only fires on real edits. private void SnapshotSavedBaseline() { - if (painter) CopyValues(painter, _savedValues); + if (painter) + { + CopyValues(painter, _savedValues); + CopyValues(painter, _lastSeenValues); + } _hasSavedBaseline = painter; _hudSavePending = false; }