[Unity] Dungeon Gunner (10) - Dungeon Creation Design [8]

suhan0304·2024년 1월 19일
0

유니티 - Dungeon Gunner

목록 보기
10/30
post-thumbnail

룸 노드 전체 선택

콘텍스트 메뉴에서 룸 노드를 모두 동시에 선택할 수 있는 메뉴 버튼을 추가해보자.

RoomNodeGraphEditor.cs

/// <summary>
/// Show the context menu
/// </summary>
private void ShowContextMenu(Vector2 mousePosition)
{
    GenericMenu menu = new GenericMenu();

    menu.AddItem(new GUIContent("Create Room Node "), false, CreateRoomNode, mousePosition);
    menu.AddSeparator("");
    menu.AddItem(new GUIContent("Select All Room Nodes"), false, SelectAllRoomNodes);

    menu.ShowAsContext();
}

/// <summary>
/// Select all room nodes
/// </summary>
private void SelectAllRoomNodes()
{
    foreach (RoomNodeSO roomnode in currentRoomNodeGraph.roomNodeList)
    {
        roomnode.isSelected = true;
    }
    GUI.changed = true;
}

이제 노드 그래프 편집기에서 우클릭 시 모든 노드 선택하기 버튼이 콘텍스트 메뉴에 추가된 것을 확인할 수 있다.

모든 노드가 선택된 것을 확인할 수 있다.


룸 노드 삭제 기능

룸 노드 그래프 편집기에서 룸 노드, 노드 간의 연결을 삭제할 수 있는 기능을 구현해보자.

RommNodeSO.cs

/// <summary>
/// Remove childID from the node (returns true if the node has been removed, false otherwise)
/// </summary>
public bool RemoveChildRoomNodeIDFromRoomNode(string childID)
{
    // if the node contatins the child ID then remove it
    if (childRoomNodeIDList.Contains(childID))
    {
        childRoomNodeIDList.Remove(childID);
        return true;
    }
    return false;
}

/// <summary>
/// Remove parentID from the node (returns true if the node has been removed, false otherwise)
/// </summary>
public bool RemoveParentRoomNodeIDFromRoomNode(string parentID)
{
    // if the node contatins the parent ID then remove it
    if (parentRoomNodeIDList.Contains(parentID))
    {
        parentRoomNodeIDList.Remove(parentID);
        return true;
    }
    return false;
}

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 (roomNodeTypeList.list[selected].isCorridor && !roomNodeTypeList.list[selected].isCorridor || !roomNodeTypeList.list[selected].isCorridor
            && roomNodeTypeList.list[selected].isCorridor || !roomNodeTypeList.list[selected].isBossRoom && roomNodeTypeList.list[selection].isBossRoom)
        {
            if (childRoomNodeIDList.Count > 0)
            {
                for (int i = childRoomNodeIDList.Count - 1; i >= 0; i--)
                {
                    // Get child room node
                    RoomNodeSO childRoomNode = roomNodeGraph.GetRoomNode(childRoomNodeIDList[i]);

                    // If the child room node is not null
                    if (childRoomNode != null)
                    {
                        // Remove childID from parent room node
                        RemoveChildRoomNodeIDFromRoomNode(childRoomNode.id);

                        // Remove parentID from child room node
                        childRoomNode.RemoveParentRoomNodeIDFromRoomNode(id);
                    }
                }
            }
        }
    }

    if (EditorGUI.EndChangeCheck())
        EditorUtility.SetDirty(this);

    GUILayout.EndArea();
}

RoomNodeGraphEditor.cs

/// <summary>
/// Show the context menu
/// </summary>
private void ShowContextMenu(Vector2 mousePosition)
{
    GenericMenu menu = new GenericMenu();

    menu.AddItem(new GUIContent("Create Room Node "), false, CreateRoomNode, mousePosition);
    menu.AddSeparator("");
    menu.AddItem(new GUIContent("Select All Room Nodes"), false, SelectAllRoomNodes);
    menu.AddSeparator("");
    menu.AddItem(new GUIContent("Delete Selected Room Node Links"), false, DeleteSelectedRoomNodeLinks);
    menu.AddItem(new GUIContent("Delete Selected Room Nodes"), false, DeleteSelectedRoomNodes);

    menu.ShowAsContext();
}

/// <summary>
/// Delete the links between the selected room nodes
/// </summary>
private void DeleteSelectedRoomNodeLinks()
{
    // Iterate through all room nodes
    foreach (RoomNodeSO roomNode in currentRoomNodeGraph.roomNodeList)
    {
        if (roomNode.isSelected && roomNode.childRoomNodeIDList.Count > 0)
        {
            for (int i = roomNode.childRoomNodeIDList.Count- 1; i >= 0; i--)
            {
                // Get child room node
                RoomNodeSO childRoomNode = currentRoomNodeGraph.GetRoomNode(roomNode.childRoomNodeIDList[i]);

                // If the child room node is selected
                if (childRoomNode != null && childRoomNode.isSelected)
                {
                    // Remove childID from parent room node
                    roomNode.RemoveChildRoomNodeIDFromRoomNode(childRoomNode.id);

                    // Remove parentID from child room node
                    childRoomNode.RemoveParentRoomNodeIDFromRoomNode(roomNode.id);
                }
            }
        }
    }
    
    //Clear all selected room nodes
    ClearAllSelectedRoomNodes();
}

룸 노드를 삭제할 때 삭제 대기자 큐를 만들어서 삭제하는 이유는 삭제 요청이 올 때마다 노드를 모두 삭제해 버리면 노드 간 연결이라던가, 노드 그래프의 노드 리스트와 같은 것들에서 오류가 발생할 수 있기 때문에 일단은 대기자 큐에 넣어놓고 삭제할 수 있는 것들을 삭제하는 방식을 사용한다.


우클릭 시에 Delete 메뉴 두 개가 추가 된 것을 확인할 수 있다.

룸 노드가 정상적으로 삭제되면서 링크도 같이 삭제되는 것을 확인할 수 있다.

이처럼 links도 잘 삭제되는 것을 확인할 수 있다.

복도에서 복도로는 정상적으로 연결되지 않는다.

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글

관련 채용 정보