편집기에서 생성한 노드를 좌클릭 한 상태로 드래그 시 움직일 수 있도록 스크립트를 작성해보자. 기존의 RoomNodeGraphEditor.cs에서 드래그 이벤트를 추가해서 작성한다.
public class RoomNodeGraphEditor : EditorWindow //편집기
{
private GUIStyle roomNodeStyle;
private static RoomNodeGraphSO currentRoomNodeGraph;
private RoomNodeSO currentRoomNode = null;
private RoomNodeTypeListSO roomNodeTypeList;
private void ProcessEvents(Event currentEvent)
{
// Get room node that mouse is over if it's null or not currently being dragged
if (currentRoomNode == null || currentRoomNode.isLeftClickDragging == false)
{
currentRoomNode = IsMouseOverRoomNode(currentEvent);
}
// if mouse isn't over a room node
if (currentRoomNode == null)
{
ProcessRoomNodeGraphEvents(currentEvent);
}
// else process room node events
else
{
// process room node events
currentRoomNode.ProcessEvents(currentEvent);
}
}
/// <summary>
/// Check to see to mouse is over a room node - if so then return the room node else return null
/// </summary>
private RoomNodeSO IsMouseOverRoomNode(Event currentEvent)
{
for (int i = currentRoomNodeGraph.roomNodeList.Count - 1; i >= 0; i--)
{
if (currentRoomNodeGraph.roomNodeList[i].rect.Contains(currentEvent.mousePosition))
{
return currentRoomNodeGraph.roomNodeList[i];
}
}
return null;
}
}
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using UnityEditor;
using UnityEngine;
public class RoomNodeSO : ScriptableObject
{
[HideInInspector] public string id;
[HideInInspector] public List<string> parentRoomNodeIDList = new List<string>();
[HideInInspector] public List<string> childRoomNodeIDList = new List<string>();
[HideInInspector] public RoomNodeGraphSO roomNodeGraph;
public RoomNodeTypeSO roomNodeType;
[HideInInspector] public RoomNodeTypeListSO roomNodeTypeList;
#region Editor Code
// the following code should only be run in the Unity Editor
#if UNITY_EDITOR
[HideInInspector] public Rect rect;
[HideInInspector] public bool isLeftClickDragging = false;
[HideInInspector] public bool isSelected = false;
/// <summary>
/// Initialise node
/// </summary>
public void Initialise(Rect rect, RoomNodeGraphSO nodeGraph, RoomNodeTypeSO roomNodeType)
{
this.rect = rect;
this.id = Guid.NewGuid().ToString();
this.name = "RoomNode";
this.roomNodeGraph = nodeGraph;
this.roomNodeType = roomNodeType;
// Load room node type list
roomNodeTypeList = GameResources.Instance.roomNodeTypeList;
}
public void Draw(GUIStyle nodeStyle)
{
// Draw Node Box Using Begin Area
GUILayout.BeginArea(rect, nodeStyle);
// Start Region To Detect Popup Selection Changes
EditorGUI.BeginChangeCheck();
// Display a popup using the RoomNodeType name values that can be selected from (default to the currently set roomNodeType)
int selected = roomNodeTypeList.list.FindIndex(x => x == roomNodeType);
int selection = EditorGUILayout.Popup("", selected, GetRoomNodeTypeToDisplay());
roomNodeType = roomNodeTypeList.list[selection];
if (EditorGUI.EndChangeCheck())
EditorUtility.SetDirty(this);
GUILayout.EndArea();
}
/// <summary>
/// Populate a string array with the room node types to display that can be selected
/// </summary>
public string[] GetRoomNodeTypeToDisplay()
{
string[] roomArray = new string[roomNodeTypeList.list.Count];
for(int i = 0; i < roomNodeTypeList.list.Count; i++)
{
if (roomNodeTypeList.list[i].displayInNodeGraphEditor)
{
roomArray[i] = roomNodeTypeList.list[i].roomNodeTypeName;
}
}
return roomArray;
}
/// <summary>
/// Process events for the node
/// </summary>
public void ProcessEvents(Event currentEvent)
{
switch(currentEvent.type)
{
// Process Mouse Down Events
case EventType.MouseDown:
ProcessMouseDownEvent(currentEvent);
break;
// Process Mouse Up Events
case EventType.MouseUp:
ProcessMouseUpEvent(currentEvent);
break;
// Process Mouse Drag Events
case EventType.MouseDrag:
ProcessMouseDragEvent(currentEvent);
break;
default:
break;
}
}
/// <summary>
/// Process mouse down events
/// </summary>
private void ProcessMouseDownEvent(Event currentEvent)
{
// If left click down
if (currentEvent.button == 0)
{
ProcessLeftClickDownEvent();
}
}
/// <summary>
/// Process left click down event
/// </summary>
private void ProcessLeftClickDownEvent()
{
Selection.activeObject = this;
// Toggle node selection
if(isSelected == true)
{
isSelected = false;
}
else
{
isSelected = true;
}
}
/// <summary>
/// Process mouse up events
/// </summary>
private void ProcessMouseUpEvent(Event currentEvent)
{
// If left click up
if (currentEvent.button == 0)
{
ProcessLeftClickUpEvent();
}
}
/// <summary>
/// Process left click up event
/// </summary>
private void ProcessLeftClickUpEvent()
{
if (isLeftClickDragging)
{
isLeftClickDragging = false;
}
}
/// <summary>
/// Process mouse drag event
/// </summary>
private void ProcessMouseDragEvent(Event currentEvent)
{
// process left click drag event
if (currentEvent.button == 0)
{
ProcessLeftMouseDragEvent(currentEvent);
}
}
/// <summary>
/// Process left mouse drag event
/// </summary>
private void ProcessLeftMouseDragEvent(Event currentEvent)
{
isLeftClickDragging = true;
DragNode(currentEvent.delta);
GUI.changed = true;
}
/// <summary>
/// Drag Node
/// </summary>
public void DragNode(Vector2 delta)
{
rect.position += delta;
EditorUtility.SetDirty(this);
}
#endif
#endregion Editor COde
}
위와 같이 RoomNodeGraphEditor에서 Event를 파악해서 currentRoomNode를 유지해준다. 실제로는 currentRoomNode만 유지해주면서 이벤트 처리, 즉 드래그 이벤트가 처리되면서 노드가 옮겨지는 내용은 실제로는 RoomNodeSO에 있다.
이제 드래그로 노드들의 위치를 조정해줄 수 있다.
private void ProcessLeftClickDownEvent() { Selection.activeObject = this; }
위 코드를 통해 노드를 클릭하면 유니티 에디터에서 해당 노드가 선택되면서 인스펙터 창이 변하는 것을 확인할 수 있다.