283 lines
8.7 KiB
C#
283 lines
8.7 KiB
C#
#nullable enable
|
|
using System.Collections.Generic;
|
|
using RTGLite;
|
|
using UnityEngine;
|
|
using UVC.Core;
|
|
using UVC.Studio.Command;
|
|
|
|
namespace UVC.Studio.Manager
|
|
{
|
|
/// <summary>
|
|
/// RTGLite Gizmo와 UndoRedoManager를 연결하는 브릿지 컴포넌트
|
|
/// Gizmo 드래그 시작/종료를 감지하여 TransformChangeCommand를 기록합니다.
|
|
/// </summary>
|
|
[DefaultExecutionOrder(200)] // RTGizmos 초기화 후 실행
|
|
public class GizmoUndoBridge : SingletonScene<GizmoUndoBridge>
|
|
{
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// 드래그 중인지 여부
|
|
/// </summary>
|
|
private bool _isDragging = false;
|
|
|
|
/// <summary>
|
|
/// 드래그 종료 후 프레임 카운터 (클릭 무시용)
|
|
/// </summary>
|
|
private int _framesSinceDragEnd = int.MaxValue;
|
|
|
|
/// <summary>
|
|
/// 현재 드래그 중인 Gizmo
|
|
/// </summary>
|
|
private Gizmo? _activeGizmo = null;
|
|
|
|
/// <summary>
|
|
/// 드래그 시작 시 캡처한 TransformChangeCommand
|
|
/// </summary>
|
|
private TransformChangeCommand? _pendingCommand = null;
|
|
|
|
/// <summary>
|
|
/// 드래그 대상 Transform 리스트 (캐시)
|
|
/// </summary>
|
|
private readonly List<Transform> _dragTargets = new();
|
|
|
|
#endregion
|
|
|
|
#region Unity Lifecycle
|
|
|
|
protected override void Init()
|
|
{
|
|
Debug.Log("[GizmoUndoBridge] Initialized");
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
// UVC UndoRedoManager 이벤트 구독
|
|
if (UndoRedoManager.Instance != null)
|
|
{
|
|
UndoRedoManager.Instance.OnUndo += OnUVCUndo;
|
|
UndoRedoManager.Instance.OnRedo += OnUVCRedo;
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
// 드래그 종료 후 프레임 카운터 증가
|
|
if (_framesSinceDragEnd < int.MaxValue)
|
|
{
|
|
_framesSinceDragEnd++;
|
|
}
|
|
|
|
// RTGizmos가 없으면 스킵
|
|
if (RTGizmos.get == null) return;
|
|
|
|
// 활성화된 드래그 Gizmo 찾기 (RTGizmos.draggedGizmo 사용)
|
|
var currentDraggingGizmo = RTGizmos.get.draggedGizmo;
|
|
|
|
// 드래그 시작 감지
|
|
if (!_isDragging && currentDraggingGizmo != null)
|
|
{
|
|
OnDragStart(currentDraggingGizmo);
|
|
}
|
|
// 드래그 종료 감지
|
|
else if (_isDragging && currentDraggingGizmo == null)
|
|
{
|
|
OnDragEnd();
|
|
}
|
|
}
|
|
|
|
protected override void OnDestroy()
|
|
{
|
|
if (UndoRedoManager.Instance != null)
|
|
{
|
|
UndoRedoManager.Instance.OnUndo -= OnUVCUndo;
|
|
UndoRedoManager.Instance.OnRedo -= OnUVCRedo;
|
|
}
|
|
|
|
base.OnDestroy();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Drag Detection
|
|
|
|
/// <summary>
|
|
/// 드래그 시작 시 호출
|
|
/// </summary>
|
|
private void OnDragStart(Gizmo gizmo)
|
|
{
|
|
_isDragging = true;
|
|
_activeGizmo = gizmo;
|
|
|
|
// 드래그 대상 수집
|
|
_dragTargets.Clear();
|
|
CollectDragTargets(gizmo);
|
|
|
|
if (_dragTargets.Count == 0)
|
|
{
|
|
Debug.LogWarning("[GizmoUndoBridge] No drag targets found");
|
|
return;
|
|
}
|
|
|
|
// Gizmo 타입에 따른 설명 생성
|
|
string description = GetGizmoOperationDescription(gizmo);
|
|
|
|
// TransformChangeCommand 생성 (Before 상태 캡처)
|
|
_pendingCommand = new TransformChangeCommand(_dragTargets, description);
|
|
|
|
Debug.Log($"[GizmoUndoBridge] Drag started: {_dragTargets.Count}개 객체, {description}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 드래그 종료 시 호출
|
|
/// </summary>
|
|
private void OnDragEnd()
|
|
{
|
|
_isDragging = false;
|
|
_framesSinceDragEnd = 0; // 프레임 카운터 리셋
|
|
|
|
if (_pendingCommand != null)
|
|
{
|
|
// After 상태 캡처
|
|
_pendingCommand.CaptureAfterState();
|
|
|
|
// 변경사항이 있으면 UndoRedoManager에 기록
|
|
if (_pendingCommand.HasChanges())
|
|
{
|
|
var undoRedoManager = UndoRedoManager.Instance;
|
|
if (undoRedoManager != null)
|
|
{
|
|
undoRedoManager.RecordCommand(_pendingCommand);
|
|
Debug.Log($"[GizmoUndoBridge] Drag ended, recorded: {_pendingCommand.Description}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("[GizmoUndoBridge] Drag ended, no changes detected");
|
|
}
|
|
}
|
|
|
|
_pendingCommand = null;
|
|
_activeGizmo = null;
|
|
_dragTargets.Clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gizmo에서 드래그 대상 Transform을 수집합니다.
|
|
/// </summary>
|
|
private void CollectDragTargets(Gizmo gizmo)
|
|
{
|
|
ObjectTransformGizmo? objectTransformGizmo = null;
|
|
|
|
// Gizmo 타입에 따라 ObjectTransformGizmo 가져오기
|
|
if (gizmo is MoveGizmo moveGizmo)
|
|
{
|
|
objectTransformGizmo = moveGizmo.objectTransformGizmo;
|
|
}
|
|
else if (gizmo is RotateGizmo rotateGizmo)
|
|
{
|
|
objectTransformGizmo = rotateGizmo.objectTransformGizmo;
|
|
}
|
|
else if (gizmo is ScaleGizmo scaleGizmo)
|
|
{
|
|
objectTransformGizmo = scaleGizmo.objectTransformGizmo;
|
|
}
|
|
|
|
if (objectTransformGizmo == null || objectTransformGizmo.targetCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// SelectionManager에서 선택된 객체 가져오기
|
|
if (InjectorAppContext.Instance != null)
|
|
{
|
|
var selectionManager = InjectorAppContext.Instance.Get<SelectionManager>();
|
|
if (selectionManager != null)
|
|
{
|
|
foreach (var stageObject in selectionManager.SelectedObjects)
|
|
{
|
|
if (stageObject.GameObject != null)
|
|
{
|
|
_dragTargets.Add(stageObject.GameObject.transform);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gizmo 타입에 따른 작업 설명을 반환합니다.
|
|
/// </summary>
|
|
private static string GetGizmoOperationDescription(Gizmo gizmo)
|
|
{
|
|
return gizmo switch
|
|
{
|
|
MoveGizmo => "객체 이동",
|
|
RotateGizmo => "객체 회전",
|
|
ScaleGizmo => "객체 크기 변경",
|
|
_ => "객체 변환"
|
|
};
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region UVC Undo/Redo Integration
|
|
|
|
/// <summary>
|
|
/// UVC UndoRedoManager의 Undo 이벤트 핸들러
|
|
/// </summary>
|
|
private void OnUVCUndo(UVC.UI.Commands.IUndoableCommand command)
|
|
{
|
|
// Transform 관련 커맨드면 RTGizmos 새로고침
|
|
if (command is TransformChangeCommand)
|
|
{
|
|
RefreshGizmos();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// UVC UndoRedoManager의 Redo 이벤트 핸들러
|
|
/// </summary>
|
|
private void OnUVCRedo(UVC.UI.Commands.IUndoableCommand command)
|
|
{
|
|
// Transform 관련 커맨드면 RTGizmos 새로고침
|
|
if (command is TransformChangeCommand)
|
|
{
|
|
RefreshGizmos();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 활성 Gizmo를 새로고침합니다.
|
|
/// PropertyWindow에서 Transform 속성 변경 시에도 호출됩니다.
|
|
/// </summary>
|
|
public void RefreshGizmos()
|
|
{
|
|
if (RTGizmos.get == null) return;
|
|
|
|
// CollectObjectTransformGizmos를 사용하여 모든 ObjectTransformGizmo 수집
|
|
var objectTransformGizmos = new List<ObjectTransformGizmo>();
|
|
RTGizmos.get.CollectObjectTransformGizmos(objectTransformGizmos);
|
|
|
|
foreach (var transformGizmo in objectTransformGizmos)
|
|
{
|
|
transformGizmo?.Refresh();
|
|
}
|
|
|
|
Debug.Log("[GizmoUndoBridge] Gizmos refreshed after Undo/Redo");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// 드래그 중이거나 드래그 직후인지 여부
|
|
/// 빈 공간 클릭 시 선택 해제 방지용
|
|
/// </summary>
|
|
public bool IsDraggingOrJustEnded => _isDragging || _framesSinceDragEnd < 2;
|
|
|
|
#endregion
|
|
}
|
|
}
|