using System.Linq; using UnityEngine; using UnityEngine.Pool; using UnityEngine.UIElements; namespace RosettaUI.UIToolkit.AnimationCurveEditor { /// /// ControlPointの編集用ポップアップ /// public class ControlPointsEditPositionPopup : EventBlocker { public static string VisualTreeAssetName { get; set; } = "RosettaUI_AnimationCurve_ControlPointEditPositionPopup"; private VisualElement _editKeyPopupRoot; private FloatField _timeField; private FloatField _valueField; private CurveController _curveController; private VisualElement _focusBackElement; public ControlPointsEditPositionPopup() { Hide(); } private void InitializeIfNeeded() { if (_timeField != null && _valueField != null) { return; // Already initialized } var visualTree = Resources.Load(VisualTreeAssetName); if (visualTree != null) { visualTree.CloneTree(this); } else { Debug.LogError($"Visual tree asset not found: {VisualTreeAssetName}"); } _editKeyPopupRoot = this.Q("EditKeyPopupRoot"); _timeField = this.Q("TimeField"); _valueField = this.Q("ValueField"); RegisterCallback(HideByEvent); RegisterCallback(evt => { switch (evt.keyCode) { case KeyCode.Escape: HideByEvent(evt); break; case KeyCode.Return or KeyCode.KeypadEnter: _curveController?.CommandForSelection.SetKeyframePosition( _timeField.showMixedValue ? null : _timeField.value, _valueField.showMixedValue ? null : _valueField.value ); HideByEvent(evt); break; } }, TrickleDown.TrickleDown); this.AddManipulator(new FocusTrapManipulator()); return; void HideByEvent(EventBase evt) { Hide(); evt.StopPropagation(); } } public void Show(Vector2 localPosition, CurveController curveController, VisualElement focusBackElement) { if (!curveController.SelectedControlPoints.Any()) { return; } InitializeIfNeeded(); _curveController = curveController; _focusBackElement = focusBackElement; using var _ = ListPool.Get(out var keyframePositions); keyframePositions.AddRange( _curveController.SelectedControlPoints.Select(cp => cp.KeyframePosition) ); var hasMultipleValueX = keyframePositions.Select(p => p.x).Distinct().Skip(1).Any(); var hasMultipleValueY = keyframePositions.Select(p => p.y).Distinct().Skip(1).Any(); _timeField.showMixedValue = hasMultipleValueX; _valueField.showMixedValue = hasMultipleValueY; if (!hasMultipleValueX) { _timeField.value = keyframePositions[0].x; } if (!hasMultipleValueY) { _valueField.value = keyframePositions[0].y; } _editKeyPopupRoot.style.left = localPosition.x; _editKeyPopupRoot.style.top = localPosition.y; style.display = DisplayStyle.Flex; _editKeyPopupRoot.RegisterCallbackOnce(_ => { _editKeyPopupRoot.ClampElementToParent(); }); schedule.Execute(() => { _valueField.Focus(); }); } public void Hide() { _focusBackElement?.Focus(); _curveController = null; _focusBackElement = null; style.display = DisplayStyle.None; } } }