- BackgroundSceneLoaderWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField) - PropBrowserWindow: OnGUI → CreateGUI (Toolbar + ToolbarSearchField) - StreamingleCommon.uss: 브라우저 공통 스타일 추가 (그리드/리스트/뷰토글/액션바/상태바) - excludeFromWeb 상태 새로고침 시 보존 수정 - 삭제된 배경 리소스 정리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
182 lines
5.9 KiB
C#
182 lines
5.9 KiB
C#
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<StyleSheet>(CommonUssPath);
|
|
if (commonUss != null) root.styleSheets.Add(commonUss);
|
|
|
|
var uxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UxmlPath);
|
|
if (uxml != null) uxml.CloneTree(root);
|
|
|
|
BuildEventGroupsSection(root);
|
|
|
|
Undo.undoRedoPerformed += OnUndoRedo;
|
|
root.RegisterCallback<DetachFromPanelEvent>(_ => 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($"이벤트 그룹 ({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 = $"이벤트 그룹 ({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"), "이벤트");
|
|
fields.Add(eventField);
|
|
|
|
item.Add(fields);
|
|
return item;
|
|
}
|
|
|
|
private void AddEventGroup()
|
|
{
|
|
Undo.RecordObject(target, "Add Event Group");
|
|
controller.eventGroups.Add(new EventController.EventGroup("새 이벤트"));
|
|
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
|
|
}
|