새로 생성한 룸 노드가 Entarnce 노드에 연결되면 잠금되서 룸 타입을 바꾸지 못하도록 룸 노드 잠금을 추가한다. 이때 룸 노드를 하나라도 생성하면 자동으로 Entrance 노드가 생성되도록 하고 Entrance 노드에 연결되야만 룸 노드가 잠금되도록 스크립트를 작성한다.
이렇게 룸 노드 타입이 결정되고 잠금이 되면 더 이상 해당 룸 노드에 대해서는 유효성 검사를 추가로 진행하지 않는다.
public class RoomNodeGraphEditor : EditorWindow //편집기
{
private GUIStyle roomNodeSelectedStyle;
private void OnEnable()
{
// Subscribe to the inspector selection changed event
Selection.selectionChanged += InspectorSelectionChanged;
// Define node layout style
roomNodeStyle = new GUIStyle();
roomNodeStyle.normal.background = EditorGUIUtility.Load("node1") as Texture2D;
roomNodeStyle.normal.textColor = Color.white;
roomNodeStyle.padding = new RectOffset(nodePadding, nodePadding, nodePadding, nodePadding);
roomNodeStyle.border = new RectOffset(nodeBorder, nodeBorder, nodeBorder, nodeBorder);
// Define selected node style
roomNodeSelectedStyle = new GUIStyle();
roomNodeSelectedStyle.normal.background = EditorGUIUtility.Load("node1 on") as Texture2D;
roomNodeSelectedStyle.normal.textColor = Color.white;
roomNodeSelectedStyle.padding = new RectOffset(nodePadding, nodePadding, nodePadding, nodePadding);
roomNodeSelectedStyle.border = new RectOffset(nodeBorder, nodeBorder, nodeBorder, nodeBorder);
// Load Room Node types
roomNodeTypeList = GameResources.Instance.roomNodeTypeList;
Selection.selectionChanged -= InspectorSelectionChanged;
}
private void OnDisable()
{
// Unsubscribe from the inspector selection changed event
}
/// <summary>
/// Process mouse down events on the room node graph (not over a node)
/// </summary>
private void ProcessMouseDownEvent(Event currentEvent)
{
// Process right click mouse down on graph event (show context menu)
if(currentEvent.button == 1)
{
ShowContextMenu(currentEvent.mousePosition);
}
// Process left click mouse down on graph event
else if(currentEvent.button == 0)
{
ClearLineDrag();
ClearAllSelectedRoomNodes();
}
/// <summary>
/// Clear selection from all room nodes
/// </summary>
private void ClearAllSelectedRoomNodes()
{
foreach (RoomNodeSO roomNode in currentRoomNodeGraph.roomNodeList)
{
if (roomNode.isSelected)
{
roomNode.isSelected = false;
GUI.changed = true;
}
}
}
/// <summary>
/// Draw room nodes in the graph window
/// </summary>
private void DrawRoomNodes()
{
// Loop through all room nodes and draw them
foreach (RoomNodeSO roomNode in currentRoomNodeGraph.roomNodeList)
{
if (roomNode.isSelected)
{
roomNode.Draw(roomNodeSelectedStyle);
}
else
{
roomNode.Draw(roomNodeStyle);
}
}
GUI.changed = true;
}
/// <summary>
/// Selection changed in the inspector
/// </summary>
private void InspectorSelectionChanged()
{
RoomNodeGraphSO roomNodeGraph = Selection.activeObject as RoomNodeGraphSO;
if (roomNodeGraph != null)
{
currentRoomNodeGraph = roomNodeGraph;
GUI.changed = true;
}
}
}
public class RoomNodeSO : ScriptableObject
{
public void Draw(GUIStyle nodeStyle)
{
// Draw Node Box Using Begin Area
GUILayout.BeginArea(rect, nodeStyle);
// Start Region To Detect Popup Selection Changes
EditorGUI.BeginChangeCheck();
// if the room node has a parent or is of type entrance then display a label else display a popupo
if (parentRoomNodeIDList.Count > 0 || roomNodeType.isEntrance)
{
// Display a label that can't be changed
EditorGUILayout.LabelField(roomNodeType.roomNodeTypeName);
}
else
{
// 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();
}
}
이제 룸 노드 생성 시 Entrance 노드가 하나 새로 생성되는 것을 확인할 수 있다.
또한 우클릭 드래그를 해서 연결된 노드, 즉 부모 노드가 생긴 노드는 잠기면서 타입이 더 이상 변경이 불가능해진다.
이제 노드를 선택 시 SelectedStyle이 따로 적용되서 선택된 노드들을 확인할 수 있다. 아래 사진처럼 Medium Room 노드가 선택된 모습을 확인할 수 있다.
이 때 노드가 아닌 공간을 클릭하면 모든 노드의 선택이 해제된다.
추가적인 룸 노드 그래프를 만들고 다른 룸 노드 그래프 편집기가 열린 상태에서 해당 룸 노드 그래프를 더블 클릭하면 해당 룸 노드 그래프가 편집기에 새로 나타나는 것을 확인할 수 있다.