using UnityEngine;
namespace LightGlue.Unity.Game
{
///
/// 全局光标/跟随平滑设置(可挂在全局预制上,与 LightGlueManager 同节点或独立)。
/// - 供 SimpleCameraPositionMarker、LightGlueCameraAimController 等读取,统一调节平滑参数。
/// - 支持本地持久化(PlayerPrefs),启动时自动加载,修改后需调用 SaveToLocal() 保存。
///
public class LightGlueCursorSettings : MonoBehaviour
{
public static LightGlueCursorSettings Instance { get; private set; }
private const string KeyPrefix = "LightGlueCursor_";
private const string KeyMarkerSmooth = KeyPrefix + "MarkerSmooth";
private const string KeyMarkerLerp = KeyPrefix + "MarkerLerp";
private const string KeyMarkerJitter = KeyPrefix + "MarkerJitter";
private const string KeyCameraSmooth = KeyPrefix + "CameraSmooth";
private const string KeyCameraLerp = KeyPrefix + "CameraLerp";
private const string KeyCameraJitter = KeyPrefix + "CameraJitter";
[Header("标记器跟随(SimpleCameraPositionMarker)")]
[Tooltip("是否对 UI 标记位置做平滑插值")]
public bool markerEnableSmoothFollow = true;
[Tooltip("位置平滑插值速度,值越大响应越快")]
public float markerPositionLerpSpeed = 100f;
[Tooltip("抖动阈值(像素),小于该距离的位移将被忽略")]
public float markerJitterThresholdPixels = 25f;
[Tooltip("平滑曲线:横轴为进度 [0,1],纵轴为插值系数。由快到慢用缓出")]
public AnimationCurve markerSmoothCurve = new AnimationCurve(
new Keyframe(0f, 0f, 0f, 2f),
new Keyframe(1f, 1f, 2f, 0f));
[Header("相机朝向跟随(LightGlueCameraAimController)")]
[Tooltip("是否对 CameraToLook 的旋转做平滑插值")]
public bool cameraAimEnableSmoothRotation = true;
[Tooltip("旋转平滑插值速度,值越大响应越快")]
public float cameraAimRotationLerpSpeed = 100f;
[Tooltip("旋转抖动阈值(角度,度),小于该角度变化将被忽略")]
public float cameraAimRotationJitterThresholdDeg = 0.5f;
[Tooltip("旋转平滑曲线:横轴为进度 [0,1],纵轴为插值系数")]
public AnimationCurve cameraAimSmoothCurve = new AnimationCurve(
new Keyframe(0f, 0f, 0f, 2f),
new Keyframe(1f, 1f, 2f, 0f));
/// 是否在 Awake 时从本地加载已保存的参数。
[Header("持久化")]
[Tooltip("启动时是否从本地(PlayerPrefs)加载上次保存的参数")]
public bool loadFromLocalOnAwake = true;
[Header("显示控制")]
[Tooltip("要控制显示/隐藏的 UI 根节点。不指定则使用本 GameObject")]
public GameObject panelRoot;
private void Awake()
{
if (Instance != null && Instance != this)
{
gameObject.SetActive(false);
Destroy(gameObject);
return;
}
Instance = this;
if(panelRoot != null) panelRoot.SetActive(false);
DontDestroyOnLoad(gameObject);
if (loadFromLocalOnAwake)
LoadFromLocal();
}
private void OnDestroy()
{
if (Instance == this)
Instance = null;
}
///
/// 从本地(PlayerPrefs)加载已保存的参数;若无记录则保持当前 Inspector 默认值。
///
public void LoadFromLocal()
{
if (PlayerPrefs.HasKey(KeyMarkerSmooth))
markerEnableSmoothFollow = PlayerPrefs.GetInt(KeyMarkerSmooth) != 0;
if (PlayerPrefs.HasKey(KeyMarkerLerp))
markerPositionLerpSpeed = PlayerPrefs.GetFloat(KeyMarkerLerp);
if (PlayerPrefs.HasKey(KeyMarkerJitter))
markerJitterThresholdPixels = PlayerPrefs.GetFloat(KeyMarkerJitter);
if (PlayerPrefs.HasKey(KeyCameraSmooth))
cameraAimEnableSmoothRotation = PlayerPrefs.GetInt(KeyCameraSmooth) != 0;
if (PlayerPrefs.HasKey(KeyCameraLerp))
cameraAimRotationLerpSpeed = PlayerPrefs.GetFloat(KeyCameraLerp);
if (PlayerPrefs.HasKey(KeyCameraJitter))
cameraAimRotationJitterThresholdDeg = PlayerPrefs.GetFloat(KeyCameraJitter);
}
///
/// 将当前参数保存到本地(PlayerPrefs),下次启动将自动加载。
///
public void SaveToLocal()
{
PlayerPrefs.SetInt(KeyMarkerSmooth, markerEnableSmoothFollow ? 1 : 0);
PlayerPrefs.SetFloat(KeyMarkerLerp, markerPositionLerpSpeed);
PlayerPrefs.SetFloat(KeyMarkerJitter, markerJitterThresholdPixels);
PlayerPrefs.SetInt(KeyCameraSmooth, cameraAimEnableSmoothRotation ? 1 : 0);
PlayerPrefs.SetFloat(KeyCameraLerp, cameraAimRotationLerpSpeed);
PlayerPrefs.SetFloat(KeyCameraJitter, cameraAimRotationJitterThresholdDeg);
PlayerPrefs.Save();
}
///
/// 恢复为代码默认值并保存到本地。
///
public void ResetToDefaultAndSave()
{
markerEnableSmoothFollow = true;
markerPositionLerpSpeed = 100f;
markerJitterThresholdPixels = 25f;
cameraAimEnableSmoothRotation = true;
cameraAimRotationLerpSpeed = 100f;
cameraAimRotationJitterThresholdDeg = 0.5f;
SaveToLocal();
}
/// 获取实际控制显示隐藏的 GameObject(panelRoot 为空则为本物体)。
private GameObject GetPanelRoot()
{
return panelRoot != null ? panelRoot : gameObject;
}
/// 显示设置面板。
public void ShowPanel()
{
GetPanelRoot().SetActive(true);
}
/// 隐藏设置面板。
public void HidePanel()
{
GetPanelRoot().SetActive(false);
}
/// 切换设置面板显示状态。
public void TogglePanel()
{
GameObject root = GetPanelRoot();
root.SetActive(!root.activeSelf);
}
/// 当前面板是否处于显示状态。
public bool IsPanelVisible()
{
return GetPanelRoot().activeSelf;
}
}
}