一個小型、無依賴的節點編輯器擴展,適用於親愛的 imgui。
Imnodes 旨在提供一個簡單的即時模式介面,用於在 ImGui 視窗中建立節點編輯器。 Imnodes 提供了使用者建立節點編輯器所需的簡單、可自訂的構建塊。
特徵:
imnodes.h
、 imnodes_internal.h
和imnodes.cpp
與 ImGui 一起複製並貼上到您的專案中。 該存儲庫包含一些範例文件,位於example/
下。它們旨在作為簡單的範例,讓您了解可以使用 imnodes 建立什麼。
如果您需要建置範例,可以使用提供的 CMake 腳本來執行此操作。
# Initialize the vcpkg submodule
$ git submodule update --init
# Run the generation step and build
$ cmake -B build-release/ -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake
$ cmake --build build-release -- -j
請注意,這尚未在 Linux 上進行測試,並且在該平台上可能會失敗。
以下是如何使用該擴充功能的簡要概述。有關範例用法的更多信息,請捲動到自述文件的底部。
在進行任何操作之前,必須對庫進行初始化。這可以與dear imgui
初始化同時完成。
ImGui::CreateContext ();
ImNodes::CreateContext ();
// elsewhere in the code...
ImNodes::DestroyContext ();
ImGui::DestroyContext ();
節點編輯器是包含節點的工作區。節點編輯器必須在視窗中實例化,就像任何其他 UI 元素一樣。
ImGui::Begin ( " node editor " );
ImNodes::BeginNodeEditor ();
ImNodes::EndNodeEditor ();
ImGui::End ();
現在您應該有一個工作區,並且在視窗中可以看到網格。現在可以實例化一個空節點:
const int hardcoded_node_id = 1 ;
ImNodes::BeginNodeEditor ();
ImNodes::BeginNode (hardcoded_node_id);
ImGui::Dummy (ImVec2( 80 . 0f , 45 . 0f ));
ImNodes::EndNode ();
ImNodes::EndNodeEditor ();
節點,就像dear imgui
中的視窗一樣,必須被唯一標識。但是我們不能使用節點標題來進行標識,因為工作區中應該可能存在許多同名的節點。相反,您只需使用整數進行標識。
屬性是節點的 UI 內容。屬性在節點的兩側都有一個引腳(小圓圈)。屬性有兩種類型:輸入屬性和輸出屬性。輸入屬性引腳位於節點的左側,輸出屬性引腳位於節點的右側。與節點一樣,引腳必須被唯一標識。
ImNodes::BeginNode (hardcoded_node_id);
const int output_attr_id = 2 ;
ImNodes::BeginOutputAttribute (output_attr_id);
// in between Begin|EndAttribute calls, you can call ImGui
// UI functions
ImGui::Text ( " output pin " );
ImNodes::EndOutputAttribute ();
ImNodes::EndNode ();
擴充功能並不真正關心屬性中的內容。它只是呈現屬性的引腳,並允許用戶在引腳之間建立連結。
可以使用BeginNodeTitleBar
和EndNodeTitleBar
將標題列新增到節點。與屬性一樣,您可以將標題列的內容放置在函數呼叫之間。請注意,必須在向節點添加屬性或其他dear imgui
UI 元素之前調用這些函數,因為節點的佈局是按順序從上到下構建的。
ImNodes::BeginNode (hardcoded_node_id);
ImNodes::BeginNodeTitleBar ();
ImGui::TextUnformatted ( " output node " );
ImNodes::EndNodeTitleBar ();
// pins and other node UI content omitted...
ImNodes::EndNode ();
使用者還必須呈現自己的節點之間的連結。連結是連接兩個屬性的曲線。連結只是一對屬性 ID。與節點和屬性一樣,連結也必須由唯一的整數值來識別:
std::vector<std::pair< int , int >> links;
// elsewhere in the code...
for ( int i = 0 ; i < links.size(); ++i)
{
const std::pair< int , int > p = links[i];
// in this case, we just use the array index of the link
// as the unique identifier
ImNodes::Link (i, p. first , p. second );
}
呼叫EndNodeEditor
後,您可以使用函數呼叫IsLinkCreated
檢查幀期間是否建立了連結:
int start_attr, end_attr;
if (ImNodes::IsLinkCreated(&start_attr, &end_attr))
{
links. push_back ( std::make_pair (start_attr, end_attr));
}
除了檢查新連結之外,您還可以檢查滑鼠遊標是否懸停在 UI 元素上:
int node_id;
if (ImNodes::IsNodeHovered(&node_id))
{
node_hovered = node_id;
}
您也可以檢查是否已選擇任何節點。可以點選節點,也可以透過點選節點並將框選擇器拖曳到節點上來選擇節點。
// Note that since many nodes can be selected at once, we first need to query the number of
// selected nodes before getting them.
const int num_selected_nodes = ImNodes::NumSelectedNodes();
if (num_selected_nodes > 0 )
{
std::vector< int > selected_nodes;
selected_nodes. resize (num_selected_nodes);
ImNodes::GetSelectedNodes (selected_nodes. data ());
}
有關更多 UI 事件相關函數,請參閱imnodes.h
。
就像dear imgui
一樣,UI 的風格是可以改變的。您可以透過呼叫ImNodes::PushColorStyle
和ImNodes::PopColorStyle
來設定單一節點、引腳和連結中幀的顏色樣式。
// set the titlebar color of an individual node
ImNodes::PushColorStyle (
ImNodesCol_TitleBar, IM_COL32( 11 , 109 , 191 , 255 ));
ImNodes::PushColorStyle (
ImNodesCol_TitleBarSelected, IM_COL32( 81 , 148 , 204 , 255 ));
ImNodes::BeginNode (hardcoded_node_id);
// node internals here...
ImNodes::EndNode ();
ImNodes::PopColorStyle ();
ImNodes::PopColorStyle ();
如果未在幀中設定樣式,則可以呼叫ImNodes::GetStyle
,並將值直接設定到樣式數組中。
// set the titlebar color for all nodes
ImNodesStyle& style = ImNodes::GetStyle();
style.colors[ImNodesCol_TitleBar] = IM_COL32( 232 , 27 , 86 , 255 );
style.colors[ImNodesCol_TitleBarSelected] = IM_COL32( 241 , 108 , 146 , 255 );
為了更快地導航大型圖形,您可以使用互動式迷你地圖疊加圖層。小地圖可以縮放和滾動。編輯器節點將相應地追蹤小地圖的平移。
ImGui::Begin ( " node editor " );
ImNodes::BeginNodeEditor ();
// add nodes...
// must be called right before EndNodeEditor
ImNodes::MiniMap ();
ImNodes::EndNodeEditor ();
ImGui::End ();
編輯器空間中小地圖的相對大小和角落位置可以這樣指定:
// MiniMap is a square region with a side length that is 20% the largest editor canvas dimension
// See ImNodesMiniMapLocation_ for other corner locations
ImNodes::MiniMap ( 0 . 2f , ImNodesMiniMapLocation_TopRight);
小地圖還支援透過使用者定義的回調進行有限的節點懸停自訂。
// User callback
void mini_map_node_hovering_callback ( int node_id, void * user_data)
{
ImGui::SetTooltip ( " This is node %d " , node_id);
}
// Later on...
ImNodes::MiniMap ( 0 . 2f , ImNodesMiniMapLocation_TopRight, mini_map_node_hovering_callback, custom_user_data);
// 'custom_user_data' can be used to supply extra information needed for drawing within the callback
可以透過提供imnodes_config.h
標頭並在編譯時指定定義IMNODES_USER_CONFIG=imnodes_config.h
來自訂 ImNodes。
目前可以覆蓋小地圖懸停回調函數的類型。這在為另一種語言產生綁定時很有用。
下面是一個範例 imnodes_config.h,它為回調產生 pybind 包裝器。
# pragma once
# include < pybind11/functional.h >
namespace pybind11 {
inline bool PyWrapper_Check (PyObject *o) { return true ; }
class wrapper : public object {
public:
PYBIND11_OBJECT_DEFAULT (wrapper, object, PyWrapper_Check)
wrapper ( void * x) { m_ptr = (PyObject*)x; }
explicit operator bool () const { return m_ptr != nullptr && m_ptr != Py_None; }
};
} // namespace pybind11
namespace py = pybind11;
# define ImNodesMiniMapNodeHoveringCallback py::wrapper
# define ImNodesMiniMapNodeHoveringCallbackUserData py::wrapper
ImGui::Separator()
跨越目前視窗範圍。因此,在節點內使用分隔符號將導致分隔符號從節點溢出到節點編輯器網格中。 請參閱examples/
目錄以更詳細地了解庫的使用情況。