Ekstensi editor node kecil dan bebas ketergantungan untuk imgui tersayang.
Imnodes bertujuan untuk menyediakan antarmuka mode langsung yang sederhana untuk membuat editor node dalam jendela ImGui. Imnodes menyediakan blok penyusun yang sederhana dan dapat disesuaikan yang dibutuhkan pengguna untuk membangun editor simpul mereka.
Fitur:
imnodes.h
, imnodes_internal.h
, dan imnodes.cpp
ke dalam proyek Anda bersama ImGui. Repositori ini mencakup beberapa file contoh, di bawah example/
. Mereka dimaksudkan sebagai contoh sederhana yang memberi Anda gambaran tentang apa yang dapat Anda bangun dengan imnodes.
Jika Anda perlu membuat contoh, Anda dapat menggunakan skrip CMake yang disediakan untuk melakukannya.
# 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
Perhatikan bahwa ini belum diuji di Linux dan kemungkinan besar gagal di platform.
Berikut ini ikhtisar kecil tentang bagaimana ekstensi digunakan. Untuk informasi lebih lanjut tentang contoh penggunaan, gulir ke bagian bawah README.
Sebelum melakukan sesuatu, perpustakaan harus diinisialisasi. Ini dapat dilakukan bersamaan dengan inisialisasi dear imgui
.
ImGui::CreateContext ();
ImNodes::CreateContext ();
// elsewhere in the code...
ImNodes::DestroyContext ();
ImGui::DestroyContext ();
Editor simpul adalah ruang kerja yang berisi simpul. Editor node harus dipakai dalam jendela, seperti elemen UI lainnya.
ImGui::Begin ( " node editor " );
ImNodes::BeginNodeEditor ();
ImNodes::EndNodeEditor ();
ImGui::End ();
Sekarang Anda harus memiliki ruang kerja dengan grid yang terlihat di jendela. Node kosong sekarang dapat dipakai:
const int hardcoded_node_id = 1 ;
ImNodes::BeginNodeEditor ();
ImNodes::BeginNode (hardcoded_node_id);
ImGui::Dummy (ImVec2( 80 . 0f , 45 . 0f ));
ImNodes::EndNode ();
ImNodes::EndNodeEditor ();
Node, seperti jendela di dear imgui
harus diidentifikasi secara unik. Tapi kita tidak bisa menggunakan judul node untuk identifikasi, karena seharusnya ada banyak node dengan nama yang sama di ruang kerja. Sebagai gantinya, Anda cukup menggunakan bilangan bulat untuk identifikasi.
Atribut adalah konten UI dari node. Sebuah atribut akan memiliki pin (lingkaran kecil) di kedua sisi node. Ada dua jenis atribut: atribut masukan dan keluaran. Pin atribut masukan berada di sisi kiri node, dan pin atribut keluaran berada di sebelah kanan. Seperti halnya node, pin harus diidentifikasi secara unik.
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 ();
Ekstensi tidak terlalu peduli dengan apa yang ada di atributnya. Itu hanya merender pin untuk atribut, dan memungkinkan pengguna membuat tautan antar pin.
Bilah judul dapat ditambahkan ke node menggunakan BeginNodeTitleBar
dan EndNodeTitleBar
. Seperti atribut, Anda menempatkan konten bilah judul di antara pemanggilan fungsi. Perhatikan bahwa fungsi-fungsi ini harus dipanggil sebelum menambahkan atribut atau elemen UI dear imgui
lainnya ke node, karena tata letak node dibuat secara berurutan, dari atas ke bawah.
ImNodes::BeginNode (hardcoded_node_id);
ImNodes::BeginNodeTitleBar ();
ImGui::TextUnformatted ( " output node " );
ImNodes::EndNodeTitleBar ();
// pins and other node UI content omitted...
ImNodes::EndNode ();
Pengguna juga harus merender tautannya sendiri antar node. Tautan adalah kurva yang menghubungkan dua atribut. Tautan hanyalah sepasang id atribut. Dan seperti node dan atribut, link juga harus diidentifikasi dengan nilai integer yang unik:
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 );
}
Setelah EndNodeEditor
dipanggil, Anda dapat memeriksa apakah tautan telah dibuat selama frame dengan pemanggilan fungsi IsLinkCreated
:
int start_attr, end_attr;
if (ImNodes::IsLinkCreated(&start_attr, &end_attr))
{
links. push_back ( std::make_pair (start_attr, end_attr));
}
Selain memeriksa tautan baru, Anda juga dapat memeriksa apakah elemen UI diarahkan oleh kursor mouse:
int node_id;
if (ImNodes::IsNodeHovered(&node_id))
{
node_hovered = node_id;
}
Anda juga dapat memeriksa apakah ada node yang dipilih. Node dapat diklik, atau dapat dipilih dengan mengklik dan menyeret pemilih kotak ke atasnya.
// 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 ());
}
Lihat imnodes.h
untuk fungsi terkait acara UI lainnya.
Seperti dear imgui
, gaya UI dapat diubah. Anda dapat mengatur gaya warna masing-masing simpul, pin, dan tautan di tengah bingkai dengan memanggil ImNodes::PushColorStyle
dan 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 ();
Jika gaya tidak disetel di tengah bingkai, ImNodes::GetStyle
dapat dipanggil, dan nilainya dapat disetel ke dalam larik gaya secara langsung.
// 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 );
Untuk menangani navigasi grafik besar yang lebih cepat, Anda dapat menggunakan hamparan peta mini interaktif. Peta mini dapat diperbesar dan digulir. Node editor akan melacak pergeseran peta mini yang sesuai.
ImGui::Begin ( " node editor " );
ImNodes::BeginNodeEditor ();
// add nodes...
// must be called right before EndNodeEditor
ImNodes::MiniMap ();
ImNodes::EndNodeEditor ();
ImGui::End ();
Ukuran relatif dan lokasi sudut peta mini di ruang editor dapat ditentukan seperti ini:
// 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);
Peta mini juga mendukung penyesuaian node terbatas yang melayang melalui panggilan balik yang ditentukan pengguna.
// 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 dapat dikustomisasi dengan menyediakan header imnodes_config.h
dan menentukan definisi IMNODES_USER_CONFIG=imnodes_config.h
saat kompilasi.
Saat ini dimungkinkan untuk mengganti jenis fungsi callback hover minimap. Ini berguna saat membuat binding untuk bahasa lain.
Berikut ini contoh imnodes_config.h, yang menghasilkan pembungkus pybind untuk panggilan balik.
# 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()
mencakup rentang jendela saat ini. Akibatnya, menggunakan pemisah di dalam sebuah node akan mengakibatkan pemisah keluar dari node ke dalam grid editor node. Lihat direktori examples/
untuk melihat penggunaan perpustakaan secara lebih rinci.