using System;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
public partial class PlayerPoseController
{
// --- Persistence: the selected pose index ---
//
// Saved on quit / play-stop and restored on the next start, so the player keeps the pose they
// had selected. Mirrors the project's other X.Persistence.cs partials (small JSON state under
// the shared MeshPaint folder).
[Header("Persistence")]
[Tooltip("Save the selected pose index on quit / play-stop and restore it on the next start. " +
"Off = the selection starts at the default pose.")]
public bool persistPose = true;
[Tooltip("Save file identifier. Empty = derived from the active scene + object name. Set " +
"explicitly to keep a save stable across object renames.")]
public string poseSaveId = "";
private const int PoseFileVersion = 1;
private bool _poseSavedOnTeardown; // guards a double save across OnApplicationQuit + OnDestroy
private static string PoseSaveDir => Path.Combine(Application.persistentDataPath, "MeshPaint");
private string PoseSavePath()
{
string key = string.IsNullOrEmpty(poseSaveId)
? SanitizePoseKey(SceneManager.GetActiveScene().name + "_" + gameObject.name)
: SanitizePoseKey(poseSaveId);
return Path.Combine(PoseSaveDir, key + ".pose");
}
private static string SanitizePoseKey(string s)
{
foreach (char c in Path.GetInvalidFileNameChars()) s = s.Replace(c, '_');
return s.Replace(' ', '_');
}
[Serializable]
private class PoseState
{
public int version = PoseFileVersion;
public int index;
}
void Start() => RestorePoseState();
private void OnApplicationQuit() => SavePoseOnTeardown();
private void OnDestroy() => SavePoseOnTeardown();
/// Saves once during teardown (OnApplicationQuit and OnDestroy both call this; only the first writes).
private void SavePoseOnTeardown()
{
if (_poseSavedOnTeardown) return;
_poseSavedOnTeardown = true;
SavePoseState();
}
/// Writes the current pose index to disk.
public void SavePoseState()
{
if (!persistPose) return;
try
{
var state = new PoseState { index = _currentIndex };
Directory.CreateDirectory(PoseSaveDir);
File.WriteAllText(PoseSavePath(), JsonUtility.ToJson(state, true));
}
catch (Exception e)
{
Debug.LogWarning($"[PlayerPoseController] Saving pose state failed: {e.Message}", this);
}
}
/// Restores the saved pose index, or does nothing if there is no save.
private void RestorePoseState()
{
if (!persistPose) return;
var state = LoadPoseState();
if (state == null) return;
SetPoseIndex(state.index);
}
private PoseState LoadPoseState()
{
string path = PoseSavePath();
if (!File.Exists(path)) return null;
try
{
var state = JsonUtility.FromJson(File.ReadAllText(path));
if (state == null || state.version != PoseFileVersion) return null;
return state;
}
catch (Exception e)
{
Debug.LogWarning($"[PlayerPoseController] Loading pose state failed: {e.Message}", this);
return null;
}
}
/// Deletes the saved pose state (next start uses the default pose). Editor convenience.
[ContextMenu("Clear Saved Pose State")]
public void ClearSavedPoseState()
{
try
{
string path = PoseSavePath();
if (File.Exists(path)) File.Delete(path);
Debug.Log($"[PlayerPoseController] Cleared saved pose state: {path}", this);
}
catch (Exception e)
{
Debug.LogWarning($"[PlayerPoseController] Clearing saved pose state failed: {e.Message}", this);
}
}
}