using System;
using RosettaUI.UndoSystem;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UIElements;
namespace RosettaUI.UIToolkit
{
///
/// ColorPicker,GradientEditor, AnimationCurveEditorなど他の操作をさせないパラメータエディター
///
public abstract class ModalEditor : VisualElement
{
protected readonly ModalWindow window;
public event Action onEditorValueChanged;
///
/// persistentSizeKeyでウィンドウサイズを保存・復元するコンストラクタ
///
protected ModalEditor(string persistentSizeKey, Vector2 defaultSize, string visualTreeAssetPath = "") : this(visualTreeAssetPath,
true)
{
Assert.IsFalse(string.IsNullOrEmpty(persistentSizeKey), $"{nameof(persistentSizeKey)} is null or empty");
if (!PersistentData.TryGet(persistentSizeKey, out var size))
{
size = defaultSize;
}
window.SetSize(size);
window.onHide += (_) => PersistentData.Set(persistentSizeKey, window.GetSize());
}
protected ModalEditor(string visualTreeAssetPath = "", bool resizable = false)
{
if (!string.IsNullOrEmpty(visualTreeAssetPath))
{
var visualTree = Resources.Load(visualTreeAssetPath);
if (visualTree != null)
{
visualTree.CloneTree(this);
}
else
{
Debug.LogError($"Visual tree asset not found: {visualTreeAssetPath}");
}
}
window = new ModalWindow(resizable);
window.Add(this);
}
protected void Show(Vector2 position, VisualElement target, Action onValueChanged, Action onHide = null)
{
onEditorValueChanged += onValueChanged;
UndoHistory.PushHistoryStack(nameof(ModalEditor));
window.onHide += OnHide;
window.RegisterCallbackOnce(_ =>
{
window.onHide -= OnHide;
onEditorValueChanged -= onValueChanged;
target?.Focus();
});
window.Show(position, target);
// 画面からはみ出さないように補正する
window.RegisterCallbackOnce(_ =>
{
VisualElementExtensions.ClampPositionToScreen(position, window);
});
return;
void OnHide(bool isCancelled)
{
// onHideでModalEditorの結果をUndoに残すケースを考慮してonHideの前にPopする
UndoHistory.PopHistoryStack();
onHide?.Invoke(isCancelled);
}
}
protected virtual void NotifyEditorValueChanged()
{
onEditorValueChanged?.Invoke(CopiedValue);
}
// TValueがクラスの場合、同じTValueインスタンスを外部で変更されるとまずい場合がある
// SetInitialValue()とGetValueForNotification()の実装を強制してTValueをCloneすべきかどうか
protected abstract TValue CopiedValue { get; set; }
}
}