#nullable enable using System.Collections.Generic; using UnityEngine; using UVC.UI.Commands; using UVC.Studio.Manager; using UVC.Studio.Config; namespace UVC.Studio.Command { /// /// 삭제 커맨드 (Undo/Redo 지원) /// public class EditDeleteCommand : IUndoableCommand { public string Description => "객체 삭제"; private readonly SelectionManager _selectionManager; private readonly StageObjectManager _stageObjectManager; // Undo용 상태 저장 private readonly List _deletedObjects = new(); /// /// 삭제된 객체 데이터 /// private class DeletedObjectData { public string OriginalId { get; set; } = string.Empty; public string ObjectName { get; set; } = string.Empty; public EquipmentItem? Equipment { get; set; } public Vector3 Position { get; set; } public Quaternion Rotation { get; set; } public Vector3 Scale { get; set; } public GameObject? RestoredGameObject { get; set; } public string? RestoredStageObjectId { get; set; } } public EditDeleteCommand(SelectionManager selectionManager, StageObjectManager stageObjectManager) { _selectionManager = selectionManager; _stageObjectManager = stageObjectManager; } public void Execute(object? parameter = null) { _deletedObjects.Clear(); var selectedObjects = new List(_selectionManager.SelectedObjects); if (selectedObjects.Count == 0) { Debug.Log("[EditDeleteCommand] 선택된 객체가 없습니다."); return; } // 먼저 선택 해제 _selectionManager.DeselectAll(); foreach (var stageObject in selectedObjects) { if (stageObject.GameObject == null) continue; // Undo용 데이터 저장 _deletedObjects.Add(new DeletedObjectData { OriginalId = stageObject.Id, ObjectName = stageObject.GameObject.name, Equipment = stageObject.Equipment, Position = stageObject.GameObject.transform.position, Rotation = stageObject.GameObject.transform.rotation, Scale = stageObject.GameObject.transform.localScale }); // 객체 제거 (Unregister가 Destroy도 수행) _stageObjectManager.Unregister(stageObject.Id); } Debug.Log($"[EditDeleteCommand] {_deletedObjects.Count}개 객체 삭제됨"); } public void Undo(object? parameter = null) { // 삭제된 객체들 복원 foreach (var data in _deletedObjects) { if (data.Equipment == null) continue; // 동일 Equipment를 가진 다른 객체를 템플릿으로 사용 GameObject? templateObject = null; foreach (var kvp in _stageObjectManager.Objects) { if (kvp.Value.Equipment?.id == data.Equipment.id && kvp.Value.GameObject != null) { templateObject = kvp.Value.GameObject; break; } } GameObject newObject; if (templateObject != null) { // 템플릿이 있으면 복제 newObject = Object.Instantiate(templateObject); } else { // 템플릿이 없으면 기본 Cube로 대체 (실제로는 Equipment.gltf 로딩 필요) newObject = GameObject.CreatePrimitive(PrimitiveType.Cube); Debug.LogWarning($"[EditDeleteCommand] 템플릿 객체를 찾을 수 없어 Cube로 대체: {data.ObjectName}"); } // Transform 복원 newObject.transform.position = data.Position; newObject.transform.rotation = data.Rotation; newObject.transform.localScale = data.Scale; newObject.name = data.ObjectName; // StageObjectManager에 등록 var restoredStageObject = _stageObjectManager.Register(data.Equipment, newObject); data.RestoredGameObject = newObject; data.RestoredStageObjectId = restoredStageObject.Id; } Debug.Log($"[EditDeleteCommand] Undo: {_deletedObjects.Count}개 객체 복원됨"); } public void Redo() { // 복원된 객체들 다시 삭제 foreach (var data in _deletedObjects) { if (data.RestoredStageObjectId != null) { _stageObjectManager.Unregister(data.RestoredStageObjectId); data.RestoredGameObject = null; data.RestoredStageObjectId = null; } } Debug.Log($"[EditDeleteCommand] Redo: {_deletedObjects.Count}개 객체 다시 삭제됨"); } public bool CanMerge(IUndoableCommand other) => false; public void Merge(IUndoableCommand other) { } } }