Replace auto paint persistence with a named painting library

Persistence rework:
- Drop auto-load on setup and auto-save on teardown; the painter now always
  seeds fresh from the material.
- Named slots under MeshPaint/Saved/<name>.paint via the existing CHMP
  machinery: SavePaintAs / LoadPaintByName / DeletePaint / ListSavedPaintings /
  PaintExists. Slot files carry the display name in the header.
- Remove the obsolete persistence partials (PlayerCharacterController,
  PlayerPoseController, ThirdPersonOrbitInput) and their references.

Paintings HUD panel:
- Authored Panel_Paintings + Save/Load/Delete dialogs into PaintHudPanel.prefab
  (TMP throughout); PaintHud.Library.cs is now a pure binder that clones the
  entry template per slot.
- Save dialog blocks empty/existing names; Load and Delete confirm first.
- Fix dialog z-order: open dialogs SetAsLastSibling so a dragged panel can no
  longer cover them.
- Lib_ListContent horizontal offsets corrected to 0 (was clipping entry labels
  out of the masked viewport).

Multiplayer:
- Loading a painting re-syncs to all peers via the snapshot broadcast path
  (BroadcastLoadedPaint), covering later late-joiners for free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-06-27 18:39:20 +02:00
1 parent 56caa0edd8
commit ee482905f9
16 files changed
+4586 -521

No files matched your search

+3 -11
View File
@@ -299,9 +299,9 @@ public partial class MeshPainter : MonoBehaviour
else if (_materialInstance.HasProperty(ColorId)) _materialInstance.SetColor(ColorId, Color.white);
BuildSeedColors();
// Persistence: seed from the saved maps if present (per-map null falls back to the
// material seed), otherwise from the material as before.
SetupBackend(useGpu, LoadPaintMaps() ?? _seedCanonical);
// Always start fresh from the material seed. Saved paintings are loaded explicitly from the
// HUD library (MeshPainter.Persistence), never auto-loaded on start.
SetupBackend(useGpu, _seedCanonical);
ConfigureMaterialPbr();
EnsureProceduralMask();
@@ -854,16 +854,8 @@ public partial class MeshPainter : MonoBehaviour
return es && es.IsPointerOverGameObject();
}
// Quit / play-stop (and standalone exit) fire OnApplicationQuit before teardown; persist
// here so the painted maps survive into the next session.
private void OnApplicationQuit() => SavePaintOnTeardown();
private void OnDestroy()
{
// Save before tearing the backend down (ReadCanonical needs the live maps). Covers a
// scene unload that does not raise OnApplicationQuit; the once-guard prevents a re-save.
SavePaintOnTeardown();
if (_bakedMesh && !_baker) Destroy(_bakedMesh); // _baker owns its mesh; only free our own
if (_materialInstance) Destroy(_materialInstance);
if (_proceduralMask) Destroy(_proceduralMask);