REFramework 依赖解析:imnodes——基于 dear imgui 的即时模式节点编辑器实战指南
发布时间:2026/10/2 16:53:21 作者:尧图编辑部 阅读量:1,286

游戏开发VR【免费下载链接】REFrameworkMod loader, scripting platform, and VR support for all RE Engine games项目地址https://gitcode.com/GitHub_Trending/re/REFramework点击查看免费下载imnodes 是 REFramework 项目dependencies/imnodes中随附的一个轻量、零第三方依赖的节点编辑器扩展库为 dear imgui 提供即时模式immediate-mode的节点图工作区能力。本指南以其官方 README 为骨架结合仓库源码逐层讲解从上下文初始化、节点/引脚/链接的创建到交互事件查询、样式定制、小地图导航与编辑器状态持久化并展示 REFramework 如何将其初始化并封装成 Lua 脚本可调用的imnodes模块。读完本文你将能够独立把 imnodes 集成进自己的 ImGui 应用搭建出可创建、连接、选择、拖拽并序列化保存的节点编辑器。一、imnodes 是什么imnodes 的定位非常明确为 dear imgui 提供一个简单、可定制的积木让使用者能够快速搭建节点编辑器同时保留对所有状态的完全控制。它的核心特性见 README.md包括即时模式创建节点、链接与引脚所有状态由用户自己持有库不替你管理业务数据模型节点内可嵌套普通 ImGui 控件节点内部就是一个 ImGui 子窗口式的容器可以直接调用ImGui::Text、ImGui::SliderFloat等任意控件极简分发只需把imnodes.h、imnodes_internal.h、imnodes.cpp三个文件与 ImGui 一起放进工程即可三个文件均位于 dependencies/imnodes。在 REFramework 中imnodes 与 ImGui、imguizmo 等同为 UI 基础设施依赖被编译进宿主进程并进一步封装为脚本 API详见下文在 REFramework 中的集成一节。构建方式与依赖官方 README 给出的构建示例依赖 vcpkg 子模块管理 imgui/SDL2# 初始化 vcpkg 子模块 $ git submodule update --init # 生成构建文件并编译 $ cmake -B build-release/ -S . -DCMAKE_BUILD_TYPERelease -DCMAKE_TOOLCHAIN_FILEvcpkg/scripts/buildsystems/vcpkg.cmake $ cmake --build build-release -- -j需要说明的是本仓库仅分发 imnodes 核心源码与 CMakeLists.txt并未包含 README 中提到的example/目录与 vcpkg 子模块。从 CMakeLists.txt 可以看到它的真实构建依赖find_package(imgui CONFIG REQUIRED) find_package(SDL2 CONFIG REQUIRED) add_library(imnodes) target_sources(imnodes PRIVATE imnodes.h imnodes_internal.h imnodes.cpp) target_link_libraries(imnodes PUBLIC imgui::imgui)即核心库imnodes只要求imgui的 CMake 包而hello、saveload、colornode、multieditor等示例可执行目标还需要 SDL2官方 README 也提示该套示例构建未在 Linux 上测试很可能失败。因此如果你只需要节点编辑器本身直接复制三个源文件即可只有构建官方示例才需要补齐 imgui、SDL2 的 CMake 包。二、初始化上下文Context的生命周期imnodes 与 dear imgui 采用相同的上下文模式。官方文档要求在使用前先创建上下文且可以紧跟 ImGui 的初始化ImGui::CreateContext(); ImNodes::CreateContext(); // elsewhere in the code... ImNodes::DestroyContext(); ImGui::DestroyContext();源码 imnodes.cpp 中CreateContext()的实现会分配ImNodesContext并在其为空时设为当前上下文ImNodesContext* CreateContext() { ImNodesContext* ctx IM_NEW(ImNodesContext)(); if (GImNodes NULL) SetCurrentContext(ctx); Initialize(ctx); return ctx; }上下文内部维护着一整套编辑器状态见 imnodes_internal.h 的ImNodesContext当前编辑器上下文EditorCtx、画布绘制列表与裁剪信息、ImNodesIO配置、ImNodesStyle样式、颜色/样式变量的修改栈Push/Pop 机制的底层存储、以及节点/引脚/链接对象池。这些对象池ImObjectPool通过IdMap把用户提供的整数 ID 映射到池内索引实现节点的按需创建与复用。跨 DLL 边界SetImGuiContext如果你把 imnodes 编译进与 ImGui 分离的 DLLGImGui全局变量不会跨 DLL 共享此时必须显式调用void SetImGuiContext(ImGuiContext* ctx);REFramework 恰好就是这种场景——宿主以 DLL 形式注入游戏进程因此它在初始化 ImGui 后立刻同步 imnodes 上下文// 见 src/REFramework.cpp#L1955-L1963D3D11 分支 IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImNodes::SetImGuiContext(ImGui::GetCurrentContext()); ImNodes::CreateContext(); set_imgui_style();D3D12 分支src/REFramework.cpp#L2018-L2026做了完全相同的处理并在脚本运行时销毁时通过api::imnodes::cleanup()见 src/mods/ScriptRunner.cpp 第 481、498 行释放相关资源。三、搭建节点编辑器工作区节点编辑器是一个容纳节点的画布workspace它像任何 UI 元素一样必须放在某个窗口内ImGui::Begin(node editor); ImNodes::BeginNodeEditor(); ImNodes::EndNodeEditor(); ImGui::End();调用BeginNodeEditor后窗口内即出现带网格的画布可以平移视图。顶层函数签名如下imnodes.hvoid BeginNodeEditor(); void EndNodeEditor();四、节点Node与唯一 ID 规则一个空节点可以这样实例化const int hardcoded_node_id 1; ImNodes::BeginNodeEditor(); ImNodes::BeginNode(hardcoded_node_id); ImGui::Dummy(ImVec2(80.0f, 45.0f)); ImNodes::EndNode(); ImNodes::EndNodeEditor();关键规则节点、引脚、链接都必须用整数唯一标识。为什么不用标题做标识因为工作区中允许存在大量同名节点标题天然不唯一。源码对 ID 的约束是可以是任意正负整数但INT_MIN被保留为内部使用imnodes.h 中BeginNode(int id)的注释。内部数据结构ImNodeData同样以int Id为核心字段且析构时会把Id置为INT_MIN作为哨兵值。每个节点的布局是自上而下、按调用顺序构建的因此后续要添加的标题栏、属性等 UI 元素必须严格按视觉顺序依次调用。节点标题栏标题栏位于节点顶部内容需放在BeginNodeTitleBar/EndNodeTitleBar之间且必须在添加任何属性或其他 UI 元素之前调用否则节点布局会错乱ImNodes::BeginNode(hardcoded_node_id); ImNodes::BeginNodeTitleBar(); ImGui::TextUnformatted(output node); ImNodes::EndNodeTitleBar(); // pins and other node UI content omitted... ImNodes::EndNode();对应 APIimnodes.hvoid BeginNodeTitleBar(); void EndNodeTitleBar(); ImVec2 GetNodeDimensions(int id);节点的可拖拽性与坐标除了拖拽移动你还可以用SetNodeDraggable(node_id, bool)单独禁用某个节点的拖拽能力。节点位置支持三种坐标系详见 imnodes.h屏幕空间screen space原点为窗口左上角编辑器空间editor space原点为节点编辑器窗口左上角网格空间grid space原点为编辑器窗口左上角再叠加当前平移量panning。对应成对 APISetNodeScreenSpacePos/GetNodeScreenSpacePos、SetNodeEditorSpacePos/GetNodeEditorSpacePos、SetNodeGridSpacePos/GetNodeGridSpacePos以及SnapNodeToGrid(node_id)当启用网格对齐样式时把节点吸附到网格。这在实现保存节点布局或程序化摆放节点时非常实用。五、属性Attribute与引脚Pin属性就是节点内部承载 UI 的内容块每个属性在节点侧边渲染一个引脚那个小圆圈。imnodes 提供三种属性输入属性Input引脚在节点左侧BeginInputAttribute(id)/EndInputAttribute()输出属性Output引脚在节点右侧BeginOutputAttribute(id)/EndOutputAttribute()静态属性Static无引脚、不可连线但同样支持活动状态检测BeginStaticAttribute(id)/EndStaticAttribute()ImNodes::BeginNode(hardcoded_node_id); const int output_attr_id 2; ImNodes::BeginOutputAttribute(output_attr_id); // 在 Begin|EndAttribute 之间可以调用任意 ImGui UI 函数 ImGui::Text(output pin); ImNodes::EndOutputAttribute(); ImNodes::EndNode();扩展并不关心属性里装了什么——它只负责渲染引脚并允许用户在引脚间建立链接。属性 ID 同样必须唯一。引脚形状BeginInputAttribute/BeginOutputAttribute的第二个参数是引脚形状可选值来自ImNodesPinShape_枚举imnodes.h枚举值说明ImNodesPinShape_Circle空心圆形ImNodesPinShape_CircleFilled实心圆形默认ImNodesPinShape_Triangle空心三角形ImNodesPinShape_TriangleFilled实心三角形ImNodesPinShape_Quad空心四边形ImNodesPinShape_QuadFilled实心四边形属性标志AttributeFlags通过PushAttributeFlag/PopAttributeFlag可以给当前属性叠加行为标志ImNodesAttributeFlags_EnableLinkDetachWithDragClick允许按住左键从引脚上拖离已有链接用户仍需自行删除该链接可用IsLinkDestroyed()检测ImNodesAttributeFlags_EnableLinkCreationOnSnap拖拽连线经过属性时触发吸附预览可提前触发IsLinkCreated/IsLinkDestroyed事件同样需要用户真正删除链接后才算完成。属性活动状态IsAttributeActive()会持续返回左键是否正在该属性 UI 内容上按下IsAnyAttributeActive(int* attribute_id)则在任意属性活动时把活动属性 ID 写回参数。这是检测拖拽 Float 控件值是否变化的便捷手段imnodes.h 注释明确提到这一用途。六、链接Link渲染、创建与销毁链接是一条连接两个引脚的曲线本质上就是一对属性 ID且同样需要唯一整数 IDstd::vectorstd::pairint, int links; // elsewhere in the code... for (int i 0; i links.size(); i) { const std::pairint, int p links[i]; // 这里直接复用数组下标作为唯一 ID ImNodes::Link(i, p.first, p.second); }Link(int id, int start_attribute_id, int end_attribute_id)中两个属性 ID 必须与Begin(Input|Output)Attribute调用时一致且start/end 顺序不影响渲染imnodes.h 明确说明。检测新链接创建EndNodeEditor()之后用IsLinkCreated检查本帧是否拖拽完成了一条新链接int start_attr, end_attr; if (ImNodes::IsLinkCreated(start_attr, end_attr)) { links.push_back(std::make_pair(start_attr, end_attr)); }它还有一个重载版本会额外返回起始/结束节点的 ID 以及是否由吸附snap触发创建bool IsLinkCreated( int* started_at_node_id, int* started_at_attribute_id, int* ended_at_node_id, int* ended_at_attribute_id, bool* created_from_snap NULL);连线交互的完整事件序列除了创建imnodes.h 还提供了完整的连线生命周期事件IsLinkStarted(int* started_at_attribute_id)用户是否从某引脚开始拖拽新链接IsLinkDropped(int* started_at_attribute_id NULL, bool including_detached_links true)拖拽的链接是否在挂接前被丢弃同时覆盖从引脚新建后丢弃与从链接分离后丢弃两种情形可用including_detached_links控制IsLinkDestroyed(int* link_id)已有链接是否被用户从引脚分离分离后用户必须自行从数据中删除该链接。这组事件在 imnodes.cpp 内部由ImNodesUIState状态位LinkStarted/LinkDropped/LinkCreated与ImClickInteractionState交互状态机共同驱动一次拖拽动作会依次触发 Started → Created/Dropped 事件。七、交互查询悬停、选择与选中管理悬停检测EndNodeEditor()之后可以查询鼠标是否悬停在某个 UI 元素上元素 ID 通过指针参数回填int node_id; if (ImNodes::IsNodeHovered(node_id)) { node_hovered node_id; }完整接口IsEditorHovered()画布是否被悬停且未被其他窗口遮挡、IsNodeHovered(int*)、IsLinkHovered(int*)、IsPinHovered(int*)。节点/链接选中节点既可以单击选中也可以通过**框选box selector**批量选中。因为选中可能同时包含多个元素需要先查询数量再取数据// 先查询选中数量再扩容取回 ID 列表 const int num_selected_nodes ImNodes::NumSelectedNodes(); if (num_selected_nodes 0) { std::vectorint selected_nodes; selected_nodes.resize(num_selected_nodes); ImNodes::GetSelectedNodes(selected_nodes.data()); }对应的还有NumSelectedLinks()/GetSelectedLinks(int*)以及细粒度的单元素管理 APISelectNode/ClearNodeSelection(node_id)/IsNodeSelected、SelectLink/ClearLinkSelection(link_id)/IsLinkSelected。注意这些 API 有前置条件Select 函数要求对象当前未选中、Clear 函数要求对象当前已选中可用对应的IsNodeSelected/IsLinkSelected先做校验。ClearNodeSelection()/ClearLinkSelection()无参版本清空整个选区典型用途是删除前先清空选中。八、样式定制颜色与样式变量imnodes 完全仿照 dear imgui 的样式体系。逐元素改色Push / PopColorStyle在帧中间对单个节点、引脚、链接临时改色// 设置单个节点的标题栏颜色 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();ImNodesCol_枚举定义了 32 种可着色元素imnodes.h覆盖节点背景/悬停/选中、节点轮廓、标题栏三种状态、链接三种状态、引脚两种状态、框选器、网格背景与主网格线、以及一整套小地图MiniMap配色背景、轮廓、节点背景、链接、画布等。全局改色GetStyle如果不想在帧中间临时修改可以直接写全局样式数组// 设置所有节点的标题栏颜色 ImNodesStyle style ImNodes::GetStyle(); style.colors[ImNodesCol_TitleBar] IM_COL32(232, 27, 86, 255); style.colors[ImNodesCol_TitleBarSelected] IM_COL32(241, 108, 146, 255);ImNodesStyle结构体imnodes.h的默认值在 imnodes.cpp 的构造函数中给出是调参时的参考基线字段默认值含义GridSpacing24.f网格间距像素NodeCornerRounding4.f节点圆角半径NodePadding(8.f, 8.f)节点内边距NodeBorderThickness1.f节点边框粗细LinkThickness3.f链接曲线粗细LinkHoverDistance10.f链接悬停判定距离PinCircleRadius4.f圆形引脚半径PinQuadSideLength7.f方形引脚边长PinTriangleSideLength9.5f三角引脚边长PinHoverRadius10.f引脚悬停判定半径PinOffset0.f引脚相对节点边缘的外扩偏移MiniMapPadding(8.f, 8.f)小地图内容内边距MiniMapOffset(4.f, 4.f)小地图距屏幕边缘偏移FlagsNodeOutline \| GridLines默认开启节点轮廓与网格线样式变量与风格预设ImNodesStyleVar_枚举对应PushStyleVar/PopStyleVar支持 float 与 ImVec2 两种值可以逐项覆盖上述样式字段。ImNodesStyleFlags_则控制整体开关NodeOutline、GridLines、GridLinesPrimary主网格线加粗、GridSnapping节点拖拽吸附网格配合SnapNodeToGrid使用。此外还提供了三个一键风格预设对齐 dear imgui 的同名风格StyleColorsDark()默认启用、StyleColorsClassic()、StyleColorsLight()都可通过dest参数指定写入目标样式实例。九、小地图MiniMap大图的快速导航对于大型节点图imnodes 内置了可交互的小地图覆盖层支持缩放与平移并会跟随编辑器视图联动。调用时机有严格要求必须在所有节点、链接绘制之后、EndNodeEditor()之前调用ImGui::Begin(node editor); ImNodes::BeginNodeEditor(); // add nodes... // 必须紧挨着 EndNodeEditor 之前调用 ImNodes::MiniMap(); ImNodes::EndNodeEditor(); ImGui::End();MiniMap的完整签名imnodes.hvoid MiniMap( const float minimap_size_fraction 0.2f, const ImNodesMiniMapLocation location ImNodesMiniMapLocation_TopLeft, const ImNodesMiniMapNodeHoveringCallback node_hovering_callback NULL, const ImNodesMiniMapNodeHoveringCallbackUserData node_hovering_callback_data NULL);minimap_size_fraction小地图是正方形区域边长取编辑器画布最大尺寸的该比例默认 0.2即 20%location四个角落可选ImNodesMiniMapLocation_BottomLeft / BottomRight / TopLeft / TopRightnode_hovering_callback鼠标悬停小地图节点时触发的用户回调用于显示 tooltip 等。// 20% 边长、右上角 ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_TopRight);带自定义悬停回调的用法// 用户回调node_id 是被悬停的节点user_data 由调用方传入 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可用于向回调传递额外信息。小地图的布局与交互状态在 imnodes_internal.h 的ImNodesEditorContext中维护MiniMapEnabled、MiniMapLocation、MiniMapSizeFraction、回调指针以及EndNodeEditor阶段计算出的屏幕空间矩形与缩放系数。十、编辑器状态持久化INI 序列化imnodes 把编辑器上下文节点位置、平移量、链接等按INI 文件格式序列化提供了字符串与文件两种途径// 序列化到字符串可用 data_size 取长度 const char* SaveCurrentEditorStateToIniString(size_t* data_size NULL); const char* SaveEditorStateToIniString(const ImNodesEditorContext* editor, size_t* data_size NULL); // 从字符串恢复 void LoadCurrentEditorStateFromIniString(const char* data, size_t data_size); void LoadEditorStateFromIniString(ImNodesEditorContext* editor, const char* data, size_t data_size); // 直接读写文件 void SaveCurrentEditorStateToIniFile(const char* file_name); void SaveEditorStateToIniFile(const ImNodesEditorContext* editor, const char* file_name); void LoadCurrentEditorStateFromIniFile(const char* file_name); void LoadEditorStateFromIniFile(ImNodesEditorContext* editor, const char* file_name);这套 API 正是官方示例save_load.cpp实现增删节点与链接、并在程序重启后保留状态的基础。需要强调的是序列化只覆盖编辑器视图状态布局/连线/平移不包含你的业务数据——节点的业务属性仍由用户自己的模型持有恢复布局后需要自行把业务数据重新关联到对应 ID 上。十一、多编辑器与视图平移控制imnodes 支持在一个窗口/上下文中管理多个独立的编辑器工作区。默认情况下库会在后台自动创建一个编辑器上下文因此最基础的用法无需显式创建但当你需要多个互不干扰的画布时可以使用ImNodesEditorContext* EditorContextCreate(); // 新建独立编辑器上下文 void EditorContextFree(ImNodesEditorContext*); // 释放 void EditorContextSet(ImNodesEditorContext*); // 设为当前活跃上下文注意文档注释明确说明一个编辑器上下文对应单个Begin/EndNodeEditor对所创建的工作区集合imnodes.h。官方示例multi_editor.cpp即演示了这一用法。配合坐标系统还提供视图平移控制EditorContextGetPanning()返回当前平移向量、EditorContextResetPanning(const ImVec2)重置平移、EditorContextMoveToNode(int node_id)将视图中心移到指定节点——非常适合搜索定位节点这类功能。十二、IO 配置鼠标行为定制ImNodes::GetIO()返回ImNodesIO结构imnodes.h用于定制鼠标交互struct ImNodesIO { struct EmulateThreeButtonMouse { const bool* Modifier; } EmulateThreeButtonMouse; struct LinkDetachWithModifierClick { const bool* Modifier; } LinkDetachWithModifierClick; struct MultipleSelectModifier { const bool* Modifier; } MultipleSelectModifier; int AltMouseButton; // 平移视图用鼠标键默认 ImGuiMouseButton_Middle float AutoPanningSpeed; // 拖拽元素出画布时自动平移速度默认 1000.0f };EmulateThreeButtonMouse.Modifier用修饰键 左键模拟中键平移视图默认 NULL禁用。启用示例ImNodes::GetIO().EmulateThreeButtonMouse.Modifier ImGui::GetIO().KeyAlt;LinkDetachWithModifierClick.Modifier按住修饰键左键点击链接即分离之默认 NULL。启用示例... ImGui::GetIO().KeyCtrl;注意用户需自行删除被分离的链接可用IsLinkDestroyed()检测MultipleSelectModifier.Modifier按住修饰键左键点击节点时追加到选中集默认 NULL 时回退到 Ctrl 键。启用示例... ImGui::GetIO().KeyCtrl;AltMouseButton默认中键ImGuiMouseButton_Middle可改为其他ImGuiMouseButton值。十三、自定义配置IMNODES_USER_CONFIGimnodes 支持通过自定义头文件进行编译期定制定义宏IMNODES_USER_CONFIGimnodes_config.h并提供一个同名头文件即可。目前可覆盖的类型是小地图悬停回调的函数指针类型——官方 README 给出的动机是为其他语言生成绑定。官方示例imnodes_config.h将回调包装为 pybind11 对象以便 Python 侧传递任意可调用对象#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在 imnodes.h 中默认的回调类型定义为#ifndef ImNodesMiniMapNodeHoveringCallback typedef void (*ImNodesMiniMapNodeHoveringCallback)(int, void*); #endif #ifndef ImNodesMiniMapNodeHoveringCallbackUserData typedef void* ImNodesMiniMapNodeHoveringCallbackUserData; #endif即头文件把两个宏用#ifndef保护IMNODES_USER_CONFIG头文件在 imnodes.h 顶部被优先包含第 6-8 行从而可以在默认 typedef 生效前覆盖它们。这种用户配置头 宏守卫的模式正是 imnodes 保持零依赖却可扩展的关键设计。十四、在 REFramework 中的实际集成宿主初始化如前文所述REFramework 在 src/REFramework.cpp#L1955-L1963D3D11 路径与 src/REFramework.cpp#L2018-L2026D3D12 路径中完成 ImGui 上下文创建后立即调用ImNodes::SetImGuiContext(ImGui::GetCurrentContext())与ImNodes::CreateContext()保证两个上下文生命周期一致。Lua 脚本绑定REFramework 进一步把 imnodes 的 API 封装进api::imnodes命名空间src/mods/bindings/ImGui.cpp 第 1662 行起并通过 sol2 注册为 Lua 全局表imnodes第 2592-2648 行。已暴露的绑定包括画布begin_node_editor、end_node_editor、is_editor_hovered节点begin_node、end_node、begin_node_titlebar、end_node_titlebar、get_node_dimensions、snap_node_to_grid、set/get_node_{screen,editor,grid}_space_pos属性begin_input_attribute、begin_output_attribute、begin_static_attribute、end_*_attribute、is_attribute_active、is_any_attribute_active链接link、is_link_started、is_link_dropped、is_link_created、is_link_destroyed、is_link_hovered选中num_selected_nodes/links、get_selected_nodes/links、select_node/link、clear_node/link_selection、is_node/link_selected样式push_color_style、pop_color_style、push_style_var、push_style_var_vec2、pop_style_var小地图minimap视图editor_move_to_node、editor_reset_panning、editor_get_panning这意味着在 REFramework 的 Lua 脚本里可以直接用imnodes.begin_node_editor()等函数搭建节点编辑器 UI例如imgui.begin(my node editor) imnodes.begin_node_editor() imnodes.begin_node(1) imnodes.begin_node_titlebar() imgui.text(hello) imnodes.end_node_titlebar() imnodes.end_node() imnodes.end_node_editor() imgui.end()十五、已知问题与注意事项官方 README 记录的已知问题ImGui::Separator()会横跨当前窗口宽度。因此在节点内部使用分隔线时分隔线会溢出节点边界、延伸到节点编辑器网格上。解决办法是避免在节点内直接使用ImGui::Separator()改用ImGui::Dummy(ImVec2(w, 0))或自定义绘制来模拟分隔。综合源码还有几点实践提醒ID 唯一性节点/引脚/链接三者各自命名空间内的 ID 必须唯一且避免使用INT_MIN调用顺序标题栏必须在属性之前调用MiniMap()必须紧邻EndNodeEditor()之前Begin/End必须严格配对否则节点布局与事件检测都会出错事件查询时机IsLinkCreated、IsLinkDestroyed、IsNodeHovered、NumSelectedNodes等交互查询都必须在EndNodeEditor()之后调用因为事件状态是在结束编辑器那一帧统一结算的分离/吸附链接需要用户配合EnableLinkDetachWithDragClick、EnableLinkCreationOnSnap、LinkDetachWithModifierClick触发的链接分离都只是视觉动作真正的数据删除必须由用户在收到IsLinkDestroyed事件后完成序列化不包含业务数据INI 持久化只负责编辑器视图状态。结语imnodes 以三个源文件实现了完整的即时模式节点编辑器上下文与对象池管理imnodes_internal.h、完整的交互事件状态机imnodes.cpp、以及贴近 dear imgui 习惯的样式/IO 定制接口imnodes.h。在 REFramework 中它不仅是渲染层的 UI 依赖更通过 src/mods/bindings/ImGui.cpp 的 sol2 绑定直接向 Lua 脚本开放。无论你是在 C 中集成还是借助 REFramework 的 Lua 环境快速原型化本文覆盖的初始化、节点/引脚/链接、事件查询、样式、小地图与序列化 API 都足以支撑一套功能完整的节点编辑器。赞分享游戏开发VR【免费下载链接】REFrameworkMod loader, scripting platform, and VR support for all RE Engine games项目地址https://gitcode.com/GitHub_Trending/re/REFramework点击查看免费下载相关推荐探索imnodes即时模式节点编辑器的卓越工具探索imnodes即时模式节点编辑器的卓越工具 项目介绍 imnodes是一个小巧且无依赖的节点编辑器扩展专为 Dear ImGui https://gitUI组件前端imgui-node-editor基于Dear ImGui的完整节点编辑器解决方案imgui node editor基于Dear ImGui的完整节点编辑器解决方案 imgui node editor是一个功能强大的节点编辑器专为游戏开发UI组件Dear ImGui与ImNodes整合节点图编辑和可视化编程框架Dear ImGui与ImNodes整合节点图编辑和可视化编程框架 引言可视化编程的新范式 在现代软件开发中可视化编程已成为提升开发效率的重要工具。传统的UI组件前端桌面应用图形学上一篇网盘下载新体验3步搞定九大网盘直链下载告别龟速等待下一篇Fast-GitHub国内开发者告别GitHub龟速下载的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考