#nullable enable using System; using UnityEngine; using UVC.Core; using UVC.Studio.Manager; using UVC.UI.Commands; using UVC.UIToolkit; namespace UVC.Studio.Command { /// /// PropertyWindow에서 속성 변경 시 사용하는 커맨드 (Undo/Redo 지원) /// public class PropertyChangeCommand : IUndoableCommand { public string Description { get; } private readonly string _propertyId; private readonly object? _oldValue; private readonly object? _newValue; private readonly Action? _applyValueAction; /// /// 생성자 /// /// 속성 ID /// 속성 이름 (표시용) /// 이전 값 /// 새 값 /// 값 적용 함수 (propertyId, value) => void public PropertyChangeCommand( string propertyId, string propertyName, object? oldValue, object? newValue, Action? applyValueAction = null) { _propertyId = propertyId; _oldValue = oldValue; _newValue = newValue; _applyValueAction = applyValueAction; Description = $"속성 변경: {propertyName}"; } public void Execute(object? parameter = null) { // 이미 PropertyWindow에서 값이 변경되었으므로 // 여기서는 추가 작업 없음 (RecordCommand용) Debug.Log($"[PropertyChangeCommand] Execute: {_propertyId} = {_newValue}"); } public void Undo(object? parameter = null) { _applyValueAction?.Invoke(_propertyId, _oldValue); Debug.Log($"[PropertyChangeCommand] Undo: {_propertyId} = {_oldValue}"); } public void Redo() { _applyValueAction?.Invoke(_propertyId, _newValue); Debug.Log($"[PropertyChangeCommand] Redo: {_propertyId} = {_newValue}"); } public bool CanMerge(IUndoableCommand other) { // 같은 속성에 대한 연속 변경은 병합 return other is PropertyChangeCommand otherCmd && otherCmd._propertyId == _propertyId; } public void Merge(IUndoableCommand other) { // 이 Command의 oldValue는 유지하고 // newValue만 최신으로 업데이트 // (불변 객체이므로 실제로는 새 Command 생성 필요하지만 // 여기서는 병합 시 새 값만 참조) } } /// /// Transform 속성 변경 전용 커맨드 /// Position, Rotation, Scale 변경 시 사용 /// public class TransformPropertyChangeCommand : IUndoableCommand { public string Description { get; } private readonly Transform _transform; private readonly string _propertyType; // "position", "rotation", "scale" private readonly Vector3 _oldValue; private readonly Vector3 _newValue; public TransformPropertyChangeCommand( Transform transform, string propertyType, Vector3 oldValue, Vector3 newValue) { _transform = transform; _propertyType = propertyType.ToLower(); _oldValue = oldValue; _newValue = newValue; Description = _propertyType switch { "position" => "위치 변경", "rotation" => "회전 변경", "scale" => "크기 변경", _ => "Transform 변경" }; } public void Execute(object? parameter = null) { ApplyValue(_newValue); } public void Undo(object? parameter = null) { ApplyValue(_oldValue); Debug.Log($"[TransformPropertyChangeCommand] Undo: {_propertyType} = {_oldValue}"); } public void Redo() { ApplyValue(_newValue); Debug.Log($"[TransformPropertyChangeCommand] Redo: {_propertyType} = {_newValue}"); } private void ApplyValue(Vector3 value) { if (_transform == null) return; switch (_propertyType) { case "position": _transform.localPosition = value; break; case "rotation": _transform.localEulerAngles = value; break; case "scale": _transform.localScale = value; break; } // PropertyWindow UI 업데이트 UpdatePropertyWindowUI(value); // Gizmo 새로고침 GizmoUndoBridge.Instance?.RefreshGizmos(); } /// /// PropertyWindow UI를 업데이트합니다. /// private void UpdatePropertyWindowUI(Vector3 value) { if (InjectorAppContext.Instance == null) return; var propertyWindow = InjectorAppContext.Instance.Get(); if (propertyWindow == null) return; string propertyId = _propertyType switch { "position" => "transform_position", "rotation" => "transform_rotation", "scale" => "transform_scale", _ => "" }; if (!string.IsNullOrEmpty(propertyId)) { propertyWindow.SetPropertyValue(propertyId, value); } } public bool CanMerge(IUndoableCommand other) { // PropertyWindow에서의 변경은 각각 독립적인 Undo로 기록 // (병합하면 중간 상태가 손실됨) return false; } public void Merge(IUndoableCommand other) { // 병합하지 않음 } } }