Files
EnglewoodLAB/Assets/Scripts/Studio/Command/PropertyChangeCommand.cs

191 lines
6.0 KiB
C#

#nullable enable
using System;
using UnityEngine;
using UVC.Core;
using UVC.Studio.Manager;
using UVC.UI.Commands;
using UVC.UIToolkit;
namespace UVC.Studio.Command
{
/// <summary>
/// PropertyWindow에서 속성 변경 시 사용하는 커맨드 (Undo/Redo 지원)
/// </summary>
public class PropertyChangeCommand : IUndoableCommand
{
public string Description { get; }
private readonly string _propertyId;
private readonly object? _oldValue;
private readonly object? _newValue;
private readonly Action<string, object?>? _applyValueAction;
/// <summary>
/// 생성자
/// </summary>
/// <param name="propertyId">속성 ID</param>
/// <param name="propertyName">속성 이름 (표시용)</param>
/// <param name="oldValue">이전 값</param>
/// <param name="newValue">새 값</param>
/// <param name="applyValueAction">값 적용 함수 (propertyId, value) => void</param>
public PropertyChangeCommand(
string propertyId,
string propertyName,
object? oldValue,
object? newValue,
Action<string, object?>? 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 생성 필요하지만
// 여기서는 병합 시 새 값만 참조)
}
}
/// <summary>
/// Transform 속성 변경 전용 커맨드
/// Position, Rotation, Scale 변경 시 사용
/// </summary>
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();
}
/// <summary>
/// PropertyWindow UI를 업데이트합니다.
/// </summary>
private void UpdatePropertyWindowUI(Vector3 value)
{
if (InjectorAppContext.Instance == null) return;
var propertyWindow = InjectorAppContext.Instance.Get<UTKPropertyTabListWindow>();
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)
{
// 병합하지 않음
}
}
}