Persist material scalars, reset the HUD, and split alpha from the picker

Save and restore the emission intensity and the three camo knobs
(half-Lambert, half-Lambert brightness, specular dampen) with a named
painting. The .paint format moves to v3 with a small scalar block
between the header and the pixel maps; v2 paintings still load with
their painter values left untouched. Loading re-syncs the emission and
camo sliders, and peers pick the values up for free through the
existing owner-authoritative paint NetworkVariables.

Add a HUD reset (Lib_ResetHud button plus context-menu fallback) that
behaves as if the saved hud-layout file were deleted: it removes the
file, restores panels to their authored prefab positions, and resets
the brush values to the painter/material defaults captured before any
carry/restore runs.

Remove the alpha bar from HsvColorPicker so alpha is driven by
standalone Slider_AlbedoAlpha / Slider_EmissionAlpha bindings; the
picker now writes RGB only and the sliders write alpha only, with no
feedback between them. Add a generic SliderCurve component that reshapes
a slider's handle position into a non-linear value (with an inverse for
setting values back), and make the slider wiring curve-aware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-06-30 18:20:13 +02:00
1 parent fe8f12b8bb
commit 057c99fa1d
7 files changed
+313 -128

No files matched your search

+21 -2
View File
@@ -21,6 +21,7 @@ public partial class PaintHud
private const string LibSaveButton = "Lib_Save";
private const string LibLoadButton = "Lib_Load";
private const string LibDeleteButton = "Lib_Delete";
private const string LibResetButton = "Lib_ResetHud";
private const string LibSaveDialog = "Lib_SaveDialog";
private const string LibNameInput = "Lib_NameInput";
private const string LibSaveInfo = "Lib_SaveInfo";
@@ -34,7 +35,7 @@ public partial class PaintHud
private bool _libraryBound;
private RectTransform _listContent;
private GameObject _entryTemplate;
private Button _saveButton, _loadButton, _deleteButton;
private Button _saveButton, _loadButton, _deleteButton, _resetButton;
private string _selectedPainting;
// Save dialog
@@ -76,9 +77,11 @@ public partial class PaintHud
_saveButton = Find<Button>(root, LibSaveButton);
_loadButton = Find<Button>(root, LibLoadButton);
_deleteButton = Find<Button>(root, LibDeleteButton);
_resetButton = Find<Button>(root, LibResetButton); // optional: present only if authored in the layout
Hook(_saveButton, OnSaveClicked);
Hook(_loadButton, OnLoadClicked);
Hook(_deleteButton, OnDeleteClicked);
Hook(_resetButton, OnResetClicked);
var sd = FindDeep(root, LibSaveDialog);
_saveDialog = sd ? sd.gameObject : null;
@@ -233,11 +236,27 @@ public partial class PaintHud
ShowConfirm($"Delete \"{name}\"?", OkDanger, () => DoDelete(name));
}
/// <summary>Reset the panels + brush values to their authored defaults (confirmed; the dialog reuses the
/// library's confirm path). Falls back to an immediate reset if no confirm dialog is authored.</summary>
private void OnResetClicked()
{
if (_confirmDialog)
ShowConfirm("Reset the HUD panels and brush values to their defaults?", OkDanger, ResetHudToDefaults);
else
ResetHudToDefaults();
}
private void DoLoad(string name)
{
if (!painter || !painter.LoadPaintByName(name)) return;
// Re-sync the loaded baseline to every other peer (no-op offline / single-player).
// The load also restored the slot's emission intensity + camo knobs onto the painter (v3 slots) ->
// push them into the sliders so the HUD reflects the loaded look, exactly like a pipette pick does.
SyncFromPainter();
SyncCamoSliders();
// Re-sync the loaded baseline to every other peer (no-op offline / single-player). The restored
// emission/camo replicate on their own via PlayerPaintSync's owner-authoritative NetworkVariables.
var sync = painter.GetComponentInParent<PlayerPaintSync>();
if (sync) sync.BroadcastLoadedPaint();
}