using UnityEngine; using UnityEditor; using UnityEngine.UIElements; using UnityEditor.UIElements; [CustomEditor(typeof(EventController))] public class EventControllerEditor : Editor { private const string UxmlPath = "Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/EventControllerEditor.uxml"; private const string CommonUssPath = "Assets/Scripts/Streamingle/StreamingleControl/Editor/UXML/StreamingleCommon.uss"; private VisualElement eventsContainer; private Label eventsTitleLabel; private EventController controller; public override VisualElement CreateInspectorGUI() { controller = (EventController)target; var root = new VisualElement(); var commonUss = AssetDatabase.LoadAssetAtPath(CommonUssPath); if (commonUss != null) root.styleSheets.Add(commonUss); var uxml = AssetDatabase.LoadAssetAtPath(UxmlPath); if (uxml != null) uxml.CloneTree(root); BuildEventGroupsSection(root); Undo.undoRedoPerformed += OnUndoRedo; root.RegisterCallback(_ => Undo.undoRedoPerformed -= OnUndoRedo); return root; } private void OnUndoRedo() { if (controller == null) return; serializedObject.Update(); RebuildEventList(); } #region Event Groups List private void BuildEventGroupsSection(VisualElement root) { var section = root.Q("eventGroupsSection"); if (section == null) return; var header = new VisualElement(); header.AddToClassList("list-header"); eventsTitleLabel = new Label($"Event Groups ({controller.eventGroups.Count})"); eventsTitleLabel.AddToClassList("list-title"); header.Add(eventsTitleLabel); var addBtn = new Button(AddEventGroup) { text = "+ 이벤트 추가" }; addBtn.AddToClassList("list-add-btn"); header.Add(addBtn); section.Add(header); eventsContainer = new VisualElement(); section.Add(eventsContainer); RebuildEventList(); } private void RebuildEventList() { if (eventsContainer == null || controller == null) return; eventsContainer.Clear(); if (eventsTitleLabel != null) eventsTitleLabel.text = $"Event Groups ({controller.eventGroups.Count})"; if (controller.eventGroups.Count == 0) { var empty = new Label("이벤트 그룹이 없습니다. '+ 이벤트 추가' 버튼을 눌러 추가하세요."); empty.AddToClassList("list-empty"); eventsContainer.Add(empty); return; } for (int i = 0; i < controller.eventGroups.Count; i++) { eventsContainer.Add(CreateEventGroupElement(i)); } } private VisualElement CreateEventGroupElement(int index) { var group = controller.eventGroups[index]; var item = new VisualElement(); item.AddToClassList("list-item"); // Header row var headerRow = new VisualElement(); headerRow.AddToClassList("list-item-header"); var indexLabel = new Label($"{index + 1}"); indexLabel.AddToClassList("list-index"); headerRow.Add(indexLabel); var nameField = new TextField(); nameField.value = group.groupName; nameField.AddToClassList("list-name-field"); int idx = index; nameField.RegisterValueChangedCallback(evt => { Undo.RecordObject(target, "Rename Event Group"); controller.eventGroups[idx].groupName = evt.newValue; EditorUtility.SetDirty(target); }); headerRow.Add(nameField); // Reorder buttons var upBtn = new Button(() => SwapEvents(idx, idx - 1)) { text = "\u25B2" }; upBtn.AddToClassList("list-reorder-btn"); upBtn.SetEnabled(index > 0); headerRow.Add(upBtn); var downBtn = new Button(() => SwapEvents(idx, idx + 1)) { text = "\u25BC" }; downBtn.AddToClassList("list-reorder-btn"); downBtn.SetEnabled(index < controller.eventGroups.Count - 1); headerRow.Add(downBtn); var deleteBtn = new Button(() => DeleteEvent(idx)) { text = "X" }; deleteBtn.AddToClassList("list-delete-btn"); headerRow.Add(deleteBtn); item.Add(headerRow); // Fields - UnityEvent uses PropertyField for the built-in event drawer var fields = new VisualElement(); fields.AddToClassList("list-fields"); var listProp = serializedObject.FindProperty("eventGroups"); var elementProp = listProp.GetArrayElementAtIndex(index); var eventField = new PropertyField(elementProp.FindPropertyRelative("unityEvent"), "Event"); fields.Add(eventField); item.Add(fields); return item; } private void AddEventGroup() { Undo.RecordObject(target, "Add Event Group"); controller.eventGroups.Add(new EventController.EventGroup("New Event")); EditorUtility.SetDirty(target); serializedObject.Update(); RebuildEventList(); } private void DeleteEvent(int index) { var group = controller.eventGroups[index]; if (EditorUtility.DisplayDialog("이벤트 삭제", $"이벤트 '{group.groupName}'을(를) 삭제하시겠습니까?", "삭제", "취소")) { Undo.RecordObject(target, "Delete Event Group"); controller.eventGroups.RemoveAt(index); EditorUtility.SetDirty(target); serializedObject.Update(); RebuildEventList(); } } private void SwapEvents(int a, int b) { Undo.RecordObject(target, "Reorder Event Groups"); (controller.eventGroups[a], controller.eventGroups[b]) = (controller.eventGroups[b], controller.eventGroups[a]); EditorUtility.SetDirty(target); serializedObject.Update(); RebuildEventList(); } #endregion }