#nullable enable using Cysharp.Threading.Tasks; using RTGLite; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; using UVC.Core; using UVC.Data.Core; using UVC.Locale; using UVC.Studio.Command; using UVC.Studio.Config; using UVC.Studio.Manager; using UVC.Studio.Modal.Settings; using UVC.Studio.UIToolkit; using UVC.Studio.Window; using UVC.UI.Commands; using UVC.UI.Tooltip; using UVC.UIToolkit; using UVC.Util; using ActionCommand = UVC.UI.Commands.ActionCommand; namespace UVC.Studio { [DefaultExecutionOrder(90)] public class StudioSceneMain : SingletonScene { [SerializeField] private GameObject? stage; /// /// Stage GameObject에 대한 외부 접근 프로퍼티 /// public GameObject? Stage => stage; [Inject] private UTKTopMenu? topMenu; [Inject] private UTKToolBar? toolBar; [Inject] private UTKTreeListWindow? explorerWindow; [Inject] private UTKAccordionListWindow? libraryWindow; [Inject] private UTKPropertyTabListWindow? propertyWindow; [Inject] private Setting? setting; [Inject] private SelectionManager? selectionManager; [Inject] private StageObjectManager? stageObjectManager; [Inject] private StaticUIDocument? StaticUIDoc; [Inject] private DynamicUIDocument? dynamicUIDoc; [Inject] private ModalUIDocument? modalUIDoc; private UIDocument? StaticUI => StaticUIDoc?.Value; private UIDocument? DynamicUI => dynamicUIDoc?.Value; private UIDocument? ModalUI => modalUIDoc?.Value; // 단축키 관리자 private ShortcutManager? shortcutManager; private UTKTreeListWindowController? componentListWindowController; private UTKAccordionListWindowController? accordionListWindowController; public Action? Initialized; /// /// 초기 화 메서드입니다. /// Awake 메서드에서 호출되며, MonoBehaviour가 생성될 때 한 번만 실행됩니다. /// protected override void Init() { if (!TooltipManager.Instance.IsInitialized) TooltipManager.Instance.Initialize(); StudioAppMain.Instance.Initialized += OnAppInitialized; } private async void OnAppInitialized() { // 초기화 완료 대기 (Injection이 수행된 후) await InjectorAppContext.Instance.WaitForInitializationAsync(); Initialize(); } private void Initialize() { SetupTopMenu(); SetupToolBar(); SetupShortcutManager(); // sideTabBar?.InitTab(); SetupSidebar(); // SelectionManager 기즈모 초기화 if (selectionManager != null) { selectionManager.InitializeGizmos(); } Initialized?.Invoke(); UTKLoading.Hide(); } private void SetupSidebar() { UTKSideBar? leftSideBar = StaticUI?.rootVisualElement.Q("leftSideBar"); UTKSideBar? rightSideBar = StaticUI?.rootVisualElement.Q("rightSideBar"); if (leftSideBar == null) { Debug.LogWarning("LeftSideBar가 StaticUI에서 발견되지 않았습니다."); return; } if (rightSideBar == null) { Debug.LogWarning("RightSideBar가 StaticUI에서 발견되지 않았습니다."); return; } componentListWindowController = new UTKTreeListWindowController(explorerWindow!); componentListWindowController.InitializeAsync().Forget(); // 다른 클래스에서 이 컨트롤러를 주입받을 수 있도록 등록 InjectorAppContext.Instance.Injector.RegisterInstance(componentListWindowController, ServiceLifetime.Scene); var explorerBtn = new UTKButton("", UTKMaterialIcons.List, UTKButton.ButtonVariant.Text, 24) { IconOnly = true, IconOnlyRadius = "0px", SizeVector = new Vector2Int(40, 40) }; leftSideBar.AddItem(explorerBtn, explorerWindow!); accordionListWindowController = new UTKAccordionListWindowController(libraryWindow!); accordionListWindowController.InitializeAsync().Forget(); // 다른 클래스에서 이 컨트롤러를 주입받을 수 있도록 등록 InjectorAppContext.Instance.Injector.RegisterInstance(accordionListWindowController, ServiceLifetime.Scene); var libraryBtn = new UTKButton("", UTKMaterialIcons.Widgets, UTKButton.ButtonVariant.Text, 24) { IconOnly = true, IconOnlyRadius = "0px", SizeVector = new Vector2Int(40, 40) }; leftSideBar.AddItem(libraryBtn, libraryWindow!); var toggleBtn = new UTKImageToggleButton( onIcon: UTKMaterialIcons.LeftPanelOpen, offIcon: UTKMaterialIcons.LeftPanelClose, iconSize: 16 ) { Size = new Vector2Int(20, 20) }; rightSideBar.AddItem(toggleBtn, propertyWindow!); rightSideBar.OnItemActivated += (int index) => { if(index == 0) { // View Gizmo의 Screen Padding 값 수정 ControllGizmoScreenPadding(true); } }; rightSideBar.OnItemDeactivated += (int index) => { if(index == 0) { // View Gizmo의 Screen Padding 값 원래대로 ControllGizmoScreenPadding(false); } }; } private void ControllGizmoScreenPadding(bool visible) { if (RTGizmos.get != null && RTGizmos.get.skin != null) { // PropertyWindow가 보이면 padding을 늘리고, 숨겨지면 원래대로 if (visible) { // X: 오른쪽 여백, Y: 위쪽 여백 (TopRight alignment 기준) RTGizmos.get.skin.viewGizmoStyle.screenPadding = new Vector2(415f, 40f); } else { RTGizmos.get.skin.viewGizmoStyle.screenPadding = new Vector2(25f, 40f); } } } private void SetupTopMenu() { if (topMenu == null) { Debug.LogWarning("TopMenuController is not assigned in SceneMain."); return; } // Setting에서 단축키 정보 가져오기 // Scene Injection이 실패할 경우 App 레벨에서 직접 가져오기 Setting? currentSetting = setting; if (currentSetting == null && InjectorAppContext.Instance != null) { currentSetting = InjectorAppContext.Instance.Get(); } MenuShortcuts? menuShortcuts = currentSetting?.Data?.shortcuts?.menu; if (menuShortcuts == null) { Debug.LogWarning("[SetupTopMenu] Setting 또는 shortcuts.menu가 null입니다. 단축키가 표시되지 않습니다."); } var menuModel = new UTKTopMenuModel(); // File 메뉴 var fileMenu = new UTKMenuItemData("file", "menu_file", subMenuItems: new List { new UTKMenuItemData("file_new", "menu_file_new", new FileNewCommand(), shortcut: menuShortcuts?.newProject?.GetDisplayString()), new UTKMenuItemData("file_open", "menu_file_open", new FileOpenCommand(), shortcut: menuShortcuts?.openProject?.GetDisplayString()), new UTKMenuItemData("file_save", "menu_file_save", new FileSaveCommand(), shortcut: menuShortcuts?.saveProject?.GetDisplayString()), new UTKMenuItemData("file_saveas", "menu_file_save_as", new FileSaveAsCommand(), shortcut: menuShortcuts?.saveAsProject?.GetDisplayString()), new UTKMenuItemData("file_insert_db", "menu_file_insert_db", new FileInsertDbCommand(), shortcut: menuShortcuts?.insertDb?.GetDisplayString()), new UTKMenuItemData("file_export", "menu_file_export", subMenuItems: new List { new UTKMenuItemData("file_export_layout", "menu_file_export_layout", new FileExportLayoutCommand(), shortcut: menuShortcuts?.exportLayout?.GetDisplayString()), new UTKMenuItemData("file_export_meta", "menu_file_export_meta", new FileExportMetaCommand(), shortcut: menuShortcuts?.exportMeta?.GetDisplayString()), new UTKMenuItemData("file_export_gltf", "menu_file_export_gltf", new FileExportGltfCommand(), shortcut: menuShortcuts?.exportGltf?.GetDisplayString()), }), }); menuModel.AddMenuItem(fileMenu); // Edit 메뉴 var editMenu = new UTKMenuItemData("edit", "menu_edit", subMenuItems: new List { new UTKMenuItemData("edit_undo", "menu_edit_undo", new EditUndoCommand(), shortcut: menuShortcuts?.undo?.GetDisplayString()), new UTKMenuItemData("edit_redo", "menu_edit_redo", new EditRedoCommand(), shortcut: menuShortcuts?.redo?.GetDisplayString()), new UTKMenuItemData("edit_duplicate", "menu_edit_duplicate", new EditDuplicateCommand(selectionManager!, stageObjectManager!), shortcut: menuShortcuts?.duplicate?.GetDisplayString()), new UTKMenuItemData("edit_delete", "menu_edit_delete", new EditDeleteCommand(selectionManager!, stageObjectManager!), shortcut: menuShortcuts?.delete?.GetDisplayString()), new UTKMenuItemData("edit_create_plane", "menu_edit_create_plane", new EditCreatePlaneCommand(stageObjectManager!), shortcut: menuShortcuts?.createPlane?.GetDisplayString()), }); menuModel.AddMenuItem(editMenu); // Setting 메뉴 var settingMenu = new UTKMenuItemData("setting", "menu_setting", subMenuItems: new List { new UTKMenuItemData("setting_db", "menu_setting_db", new SettingOpenCommand("shortcut:Database")), new UTKMenuItemData("setting_general", "menu_setting_general", new SettingOpenCommand("shortcut:General")), new UTKMenuItemData("setting_library", "menu_setting_library", new SettingOpenCommand("shortcut:Library")), new UTKMenuItemData("setting_shortcut", "menu_setting_shortcut", new SettingOpenCommand("shortcut:Shortcut")), }); menuModel.AddMenuItem(settingMenu); topMenu.CreateMenuItems(menuModel.MenuItems); } /// /// Setting에서 단축키가 변경된 후 TopMenu의 단축키를 갱신합니다. /// public void RefreshMenuShortcuts() { if (topMenu == null) return; Setting? currentSetting = setting; if (currentSetting == null && InjectorAppContext.Instance != null) { currentSetting = InjectorAppContext.Instance.Get(); } MenuShortcuts? menuShortcuts = currentSetting?.Data?.shortcuts?.menu; if (menuShortcuts == null) { Debug.LogWarning("[RefreshMenuShortcuts] Setting 또는 shortcuts.menu가 null입니다."); return; } // File 메뉴 단축키 업데이트 topMenu.UpdateShortcutText("file_new", menuShortcuts.newProject?.GetDisplayString()); topMenu.UpdateShortcutText("file_open", menuShortcuts.openProject?.GetDisplayString()); topMenu.UpdateShortcutText("file_save", menuShortcuts.saveProject?.GetDisplayString()); topMenu.UpdateShortcutText("file_saveas", menuShortcuts.saveAsProject?.GetDisplayString()); topMenu.UpdateShortcutText("file_insert_db", menuShortcuts.insertDb?.GetDisplayString()); topMenu.UpdateShortcutText("file_export_layout", menuShortcuts.exportLayout?.GetDisplayString()); topMenu.UpdateShortcutText("file_export_meta", menuShortcuts.exportMeta?.GetDisplayString()); topMenu.UpdateShortcutText("file_export_gltf", menuShortcuts.exportGltf?.GetDisplayString()); // Edit 메뉴 단축키 업데이트 topMenu.UpdateShortcutText("edit_undo", menuShortcuts.undo?.GetDisplayString()); topMenu.UpdateShortcutText("edit_redo", menuShortcuts.redo?.GetDisplayString()); topMenu.UpdateShortcutText("edit_duplicate", menuShortcuts.duplicate?.GetDisplayString()); topMenu.UpdateShortcutText("edit_delete", menuShortcuts.delete?.GetDisplayString()); topMenu.UpdateShortcutText("edit_create_plane", menuShortcuts.createPlane?.GetDisplayString()); // ShortcutManager 갱신 shortcutManager?.RefreshShortcuts(); Debug.Log("[RefreshMenuShortcuts] TopMenu 단축키가 갱신되었습니다."); } /// /// 단축키 관리자를 설정합니다. /// private void SetupShortcutManager() { // StudioShortcutManager 생성 또는 가져오기 shortcutManager = ShortcutManager.Instance; if (shortcutManager == null) { var go = new GameObject("StudioShortcutManager"); shortcutManager = go.AddComponent(); DontDestroyOnLoad(go); } // Setting 주입 Setting? currentSetting = setting; if (currentSetting == null && InjectorAppContext.Instance != null) { currentSetting = InjectorAppContext.Instance.Get(); } if (currentSetting != null) { shortcutManager.SetSetting(currentSetting); } // 메뉴 단축키 등록 RegisterMenuShortcuts(); // 도구 단축키 등록 RegisterToolShortcuts(); Debug.Log("[SetupShortcutManager] 단축키 관리자가 설정되었습니다."); } /// /// 메뉴 단축키를 등록합니다. /// private void RegisterMenuShortcuts() { if (shortcutManager == null) return; // File 메뉴 shortcutManager.RegisterMenuShortcut("newProject", new FileNewCommand()); shortcutManager.RegisterMenuShortcut("openProject", new FileOpenCommand()); shortcutManager.RegisterMenuShortcut("saveProject", new FileSaveCommand()); shortcutManager.RegisterMenuShortcut("saveAsProject", new FileSaveAsCommand()); shortcutManager.RegisterMenuShortcut("insertDb", new FileInsertDbCommand()); shortcutManager.RegisterMenuShortcut("exportLayout", new FileExportLayoutCommand()); shortcutManager.RegisterMenuShortcut("exportMeta", new FileExportMetaCommand()); shortcutManager.RegisterMenuShortcut("exportGltf", new FileExportGltfCommand()); // Edit 메뉴 shortcutManager.RegisterMenuShortcut("undo", new EditUndoCommand()); shortcutManager.RegisterMenuShortcut("redo", new EditRedoCommand()); shortcutManager.RegisterMenuShortcut("duplicate", new EditDuplicateCommand(selectionManager!, stageObjectManager!)); shortcutManager.RegisterMenuShortcut("delete", new EditDeleteCommand(selectionManager!, stageObjectManager!)); shortcutManager.RegisterMenuShortcut("createPlane", new EditCreatePlaneCommand(stageObjectManager!)); } /// /// 도구 단축키를 등록합니다. /// private void RegisterToolShortcuts() { if (shortcutManager == null) return; // 도구 단축키 - SelectionManager를 통해 기즈모 제어 shortcutManager.RegisterToolShortcut("select", () => { if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Select); if (toolBar != null) toolBar.SetRadioButtonSelection("SizeControlGroup", "Selection Tool"); }); shortcutManager.RegisterToolShortcut("move", () => { if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Move); if (toolBar != null) toolBar.SetRadioButtonSelection("SizeControlGroup", "Movement Tool"); }); shortcutManager.RegisterToolShortcut("rotate", () => { if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Rotate); if (toolBar != null) toolBar.SetRadioButtonSelection("SizeControlGroup", "Rotation Tool"); }); shortcutManager.RegisterToolShortcut("scale", () => { if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Scale); if (toolBar != null) toolBar.SetRadioButtonSelection("SizeControlGroup", "Scale Tool"); }); shortcutManager.RegisterToolShortcut("snap", () => { Debug.Log("[Shortcut] Snap Tool 토글"); if( toolBar != null) toolBar.SetToggleButtonState("Snap Tool", !(toolBar.GetToggleButtonState("Snap Tool")!.Value)); }); shortcutManager.RegisterToolShortcut("guide", () => { Debug.Log("[Shortcut] Guide Tool 토글"); if( toolBar != null) toolBar.SetToggleButtonState("Guide Tool", !(toolBar.GetToggleButtonState("Guide Tool")!.Value)); }); shortcutManager.RegisterToolShortcut("node", () => { if (toolBar != null) toolBar.SetRadioButtonSelection("NodeControlGroup", "Node Tool"); CursorManager.Instance.SetCursor(CursorType.Node); }); shortcutManager.RegisterToolShortcut("link", () => { if (toolBar != null) toolBar.SetRadioButtonSelection("NodeControlGroup", "Link Tool"); CursorManager.Instance.SetCursor(CursorType.Link); }); shortcutManager.RegisterToolShortcut("arc", () => { if (toolBar != null) toolBar.SetRadioButtonSelection("NodeControlGroup", "Arc Tool"); CursorManager.Instance.SetCursor(CursorType.Arc); }); } private void SetupToolBar() { // ToolbarModel 인스턴스 생성 var toolbarModel = new UTKToolBarModel(); // --- 툴바 모델 구성 시작 --- // 저장 toolbarModel.AddToggleButton("button_save", false, StudioUTKImageIcons.ToolbarIconSaveOn40, StudioUTKImageIcons.ToolbarIconSaveOff40, onToggle: (isSelected) => Debug.Log($"화면 녹화 상태: {(isSelected ? "녹화 중" : "중지")} (OnToggle 콜백)"), command: new FileSaveCommand(), tooltip: "tooltip_save", useMaterialIcon: false); // undo toolbarModel.AddStandardButton("button_undo", StudioUTKImageIcons.ToolbarIconUndo40, command: new EditUndoCommand(), tooltip: "tooltip_undo", useMaterialIcon: false); // redo toolbarModel.AddStandardButton("button_redo", StudioUTKImageIcons.ToolbarIconRedo40, command: new EditRedoCommand(), tooltip: "tooltip_redo", useMaterialIcon: false); toolbarModel.AddSeparator(); //select toolbarModel.AddRadioButton("SizeControlGroup", "Selection Tool", true, StudioUTKImageIcons.ToolbarIconSelectOff40, StudioUTKImageIcons.ToolbarIconSelectOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Selection Tool 선택됨"); }, command: new ActionCommand(() => { Debug.Log("Selection Tool Command 실행"); if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Select); }), "tooltip_selection_tool", useMaterialIcon: false); // move toolbarModel.AddRadioButton("SizeControlGroup", "Movement Tool", false, StudioUTKImageIcons.ToolbarIconMoveOff40, StudioUTKImageIcons.ToolbarIconMoveOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Movement Tool 선택됨"); }, command: new ActionCommand(() => { Debug.Log("Movement Tool Command 실행"); if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Move); }), "tooltip_movement_tool", useMaterialIcon: false); // rotate toolbarModel.AddRadioButton("SizeControlGroup", "Rotation Tool", false, StudioUTKImageIcons.ToolbarIconRotateOff40, StudioUTKImageIcons.ToolbarIconRotateOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Rotation Tool 선택됨"); }, command: new ActionCommand(() => { Debug.Log("Rotation Tool Command 실행"); if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Rotate); }), "tooltip_rotation_tool", useMaterialIcon: false); //scale toolbarModel.AddRadioButton("SizeControlGroup", "Scale Tool", false, StudioUTKImageIcons.ToolbarIconScaleOff40, StudioUTKImageIcons.ToolbarIconScaleOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Scale Tool 선택됨"); }, command: new ActionCommand(() => { Debug.Log("Scale Tool Command 실행"); if (selectionManager != null) selectionManager.SetActiveTool(TransformToolType.Scale); }), "tooltip_scale_tool", useMaterialIcon: false); toolbarModel.AddSeparator(); //duplicate toolbarModel.AddStandardButton("button_duplicate", StudioUTKImageIcons.ToolbarIconDuplicate40, command: new EditDuplicateCommand(selectionManager!, stageObjectManager!), tooltip: "tooltip_duplicate", useMaterialIcon: false); //delete toolbarModel.AddStandardButton("button_delete", StudioUTKImageIcons.ToolbarIconDelete40, command: new EditDeleteCommand(selectionManager!, stageObjectManager!), tooltip: "tooltip_delete", useMaterialIcon: false); //align var alignBtnModel = toolbarModel.AddExpandableButton("button_align", UTKMaterialIcons.FormatAlignCenter, new ActionCommand(() => Debug.Log("align 주 버튼 클릭됨 (Command)")), "tooltip_align", false); alignBtnModel.OnSubButtonSelected = (selectedSubButtonModel) => { // LocalizationManager를 사용하여 텍스트를 현재 언어에 맞게 가져올 수 있습니다. string localizedSubButtonText = LocalizationManager.Instance != null ? LocalizationManager.Instance.GetString(selectedSubButtonModel.Text) : selectedSubButtonModel.Text; Debug.Log($"정렬 옵션 '{localizedSubButtonText}' 선택됨 (OnSubButtonSelected 콜백). 주 버튼 업데이트 로직 실행 가능."); }; // 확장 버튼 모델에 하위 버튼 추가 alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "horizontal_left", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignHorizontalLeft, // 하위 버튼 아이콘 Tooltip = "tooltip_horizontal_left", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("왼쪽 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "horizontal_center", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignHorizontalCenter, // 하위 버튼 아이콘 Tooltip = "tooltip_horizontal_center", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("중앙 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "horizontal_right", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignHorizontalRight, // 하위 버튼 아이콘 Tooltip = "tooltip_horizontal_right", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("오른쪽 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "vertical_top", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignVerticalTop, // 하위 버튼 아이콘 Tooltip = "tooltip_vertical_top", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("위쪽 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "vertical_middle", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignVerticalCenter, // 하위 버튼 아이콘 Tooltip = "tooltip_vertical_middle", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("중앙 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "vertical_bottom", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignVerticalBottom, // 하위 버튼 아이콘 Tooltip = "tooltip_vertical_bottom", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("아래쪽 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "horizontal_even", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignJustifySpaceEven, // 하위 버튼 아이콘 Tooltip = "tooltip_horizontal_even", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("가로 균등 정렬 선택됨 (Sub-Command 실행)") }); alignBtnModel.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "vertical_even", // 하위 버튼 텍스트/키 IconPath = UTKMaterialIcons.AlignSpaceEven, // 하위 버튼 아이콘 Tooltip = "tooltip_vertical_even", // 하위 버튼 툴팁 ClickCommand = new DebugLogCommand("세로 균등 정렬 선택됨 (Sub-Command 실행)") }); //snap toolbarModel.AddToggleButton("button_snap", true, StudioUTKImageIcons.ToolbarIconSnap40, StudioUTKImageIcons.ToolbarIconSnap40, command: new DebugLogCommand("snap 버튼 클릭됨"), tooltip: "tooltip_snap", useMaterialIcon: false); //guide toolbarModel.AddToggleButton("button_guide", true, StudioUTKImageIcons.ToolbarIconGuide40, StudioUTKImageIcons.ToolbarIconGuide40, command: new DebugLogCommand("guide 버튼 클릭됨"), tooltip: "tooltip_guide", useMaterialIcon: false); toolbarModel.AddSeparator(); //node toolbarModel.AddRadioButton("NodeControlGroup", "Node Tool", false, StudioUTKImageIcons.ToolbarIconNodeOn40, StudioUTKImageIcons.ToolbarIconNodeOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Node Tool 선택됨"); }, command: new ActionCommand(() => CursorManager.Instance.SetCursor(CursorType.Node)), "tooltip_node_tool", useMaterialIcon: false); //link toolbarModel.AddRadioButton("NodeControlGroup", "Link Tool", false, StudioUTKImageIcons.ToolbarIconLinkOn40, StudioUTKImageIcons.ToolbarIconLinkOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Link Tool 선택됨"); }, command: new ActionCommand(() => CursorManager.Instance.SetCursor(CursorType.Link)), "tooltip_link_tool", useMaterialIcon: false); //arc toolbarModel.AddRadioButton("NodeControlGroup", "Arc Tool", false, StudioUTKImageIcons.ToolbarIconArcOn40, StudioUTKImageIcons.ToolbarIconArcOff40, onToggle: (isSelected) => { if (isSelected) Debug.Log("Arc Tool 선택됨"); }, command: new ActionCommand(() => CursorManager.Instance.SetCursor(CursorType.Arc)), "tooltip_arc_tool", useMaterialIcon: false); // --- 툴바 모델 구성 끝 --- toolBar?.BuildToolBar(toolbarModel); toolBar!.OnAction += (UTKToolBarActionEventArgs itemModel) => { Debug.Log($"툴박스 아이템 '{itemModel.Text}' 실행됨 (OnAction 콜백). 추가 동작 로직 실행 가능."); if (itemModel.ActionType == UTKToolBarActionType.Radio) { if (itemModel.Text == "SizeControlGroup") { // 선택, 이동, 회전, 크기 조절 툴 관련 동작 처리 toolBar.ClearRadioButtonSelection("NodeControlGroup"); CursorManager.Instance.SetDefaultCursor(); } else if (itemModel.Text == "NodeControlGroup") { // 노드, 링크, 아크 툴 관련 동작 처리 toolBar.ClearRadioButtonSelection("SizeControlGroup"); } } }; } } }