#include "Nodes_And_Connectors.hpp" #include "imgui_internal.h" // 客制化圆形带X按钮 bool CircleButtonWithX(const char *id, float radius) { ImGuiWindow *window = ImGui::GetCurrentWindow(); if (window->SkipItems) return false; // 创建ID ImGuiID button_id = window->GetID(id); // 计算按钮位置和大小 ImVec2 pos = window->DC.CursorPos; ImVec2 size(radius * 2, radius * 2); ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y)); // 处理交互 ImGui::ItemSize(bb); if (!ImGui::ItemAdd(bb, button_id)) return false; bool hovered, held; bool pressed = ImGui::ButtonBehavior(bb, button_id, &hovered, &held); // 绘制 ImU32 col = ImGui::GetColorU32( held ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); // 获取绘制列表 ImDrawList *draw_list = ImGui::GetWindowDrawList(); ImVec2 center = ImVec2(pos.x + radius, pos.y + radius); // 绘制圆形 draw_list->AddCircleFilled(center, radius, col, 32); // 绘制边框(可选) draw_list->AddCircle(center, radius, ImGui::GetColorU32(ImGuiCol_Border), 32, 1.0f); // 计算X的线条 float cross_radius = radius * 0.5f; // X的大小 float thickness = radius * 0.15f; // X的粗细 // 绘制X的两条线 draw_list->AddLine( ImVec2(center.x - cross_radius, center.y - cross_radius), ImVec2(center.x + cross_radius, center.y + cross_radius), ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X thickness); draw_list->AddLine( ImVec2(center.x + cross_radius, center.y - cross_radius), ImVec2(center.x - cross_radius, center.y + cross_radius), ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X thickness); return pressed; } // ================================================================================================= // 必要构造 Abs_Connector::Abs_Connector(Independent_ID_Generator *ID_Generator, Connector_Type_Enum type, const char *socket_str) : ID_Generator(nullptr), id(-1), type(CONNECTOR_TYPE_UNKNOWN), socket_str(nullptr) { // 分配ID this->id = ID_Generator->Request_ID(); if (this->id != -1) { this->ID_Generator = ID_Generator; this->type = type; this->socket_str = socket_str; } // 指针初始化 this->product = nullptr; this->provider = nullptr; }; // 析构 Abs_Connector::~Abs_Connector() { // 释放产物 if (this->product != nullptr) free(product); // 断开连接 this->Disconnect(); // 释放ID this->ID_Generator->Release_ID(this->id); } // 连接到目标连接点 bool Abs_Connector::Connect_To(Abs_Connector *target) { // 判定接口是否匹配 if (strcmp(target->socket_str, this->socket_str) == 0) { // 写连接关系 if ((this->type == CONNECTOR_TYPE_OUTPUT) && (target->type == CONNECTOR_TYPE_INPUT)) { target->provider = this; this->receiver_list.push_back(target); return true; } if ((this->type == CONNECTOR_TYPE_INPUT) && (target->type == CONNECTOR_TYPE_OUTPUT)) { target->receiver_list.push_back(this); this->provider = target; return true; } } return false; } // 断开连接 void Abs_Connector::Disconnect(void) { // 受点断开供方连接 if (this->type == CONNECTOR_TYPE_INPUT) { // 断开供方对自身的记录 for (auto iterator = this->provider->receiver_list.begin(); iterator != this->provider->receiver_list.end(); iterator++) { // 供方断开自身列表记录 if ((*iterator) == this) { this->provider->receiver_list.erase(iterator); break; } } // 断开自身对供方的记录 this->provider = nullptr; } // 供方断开所有受点的供方记录 if (this->type == CONNECTOR_TYPE_OUTPUT) { // 断开受点的供方记录 for (auto receiver : this->receiver_list) receiver->provider = nullptr; // 清空受点列表 decltype(this->receiver_list) empty_list; this->receiver_list.swap(empty_list); } } // 注册产物 bool Abs_Connector::Register_Product(void *product, size_t size) { // 非输出类接口 if (this->type != CONNECTOR_TYPE_OUTPUT) return false; // 释放之前的产物 if (this->product != nullptr) free(this->product); // 分配空间 this->product = malloc(size); if (this->product == nullptr) return false; // 复制内容 memcpy(this->product, product, size); return true; } // 获取上级节点 Abs_Connector *Abs_Connector::Get_Provider(void) { return this->provider; } // 获取产物 void *Abs_Connector::Get_Product(void) { // 输出节点返回直接产物 if (this->type == CONNECTOR_TYPE_OUTPUT) return this->product; // 输入节点返回间接产物(提供者方产物) if (this->type == CONNECTOR_TYPE_INPUT) { if (this->provider == nullptr) return nullptr; return this->provider->product; } // 未知类型 return nullptr; } // 获取ID int Abs_Connector::Get_ID(void) { return this->id; } // ================================================================================================= // 必要构造 Abs_Node::Abs_Node(Independent_ID_Generator *Node_ID_Generator, Independent_ID_Generator *Connector_ID_Generator, Node_Type_Enum type, ImVec2 initial_position) : Node_ID_Generator(nullptr), Connector_ID_Generator(nullptr), id(-1), type(NODE_TYPE_UNKNOWN), initial_position(initial_position) { // 分配ID this->id = Node_ID_Generator->Request_ID(); if (this->id != -1) { this->Node_ID_Generator = Node_ID_Generator; this->Connector_ID_Generator = Connector_ID_Generator; this->type = type; } this->close_flag = false; } // 析构 Abs_Node::~Abs_Node() { // 释放ID this->Node_ID_Generator->Release_ID(this->id); } // 获取关闭信号 bool Abs_Node::Get_CloseFlag(void) { return this->close_flag; } // 获取接口列表 std::vector> &Abs_Node::Get_Connector_List(void) { return this->Connector_List; } // ================================================================================================= // 必要构造 MSG_OutPut_Connector::MSG_OutPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "DLT MSG") {} // 绘制接口 void MSG_OutPut_Connector::Show(void) { // 输出接口点 ImNodes::BeginOutputAttribute(this->id, 1); ImNodes::EndOutputAttribute(); } // 必要构造 MSG_InPut_Connector::MSG_InPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_INPUT, "DLT MSG") {} // 绘制接口 void MSG_InPut_Connector::Show(void) { // 输出接口点 ImNodes::BeginInputAttribute(this->id, 1); ImNodes::EndInputAttribute(); } // ================================================================================================= // 必要构造 MSG_Input_Node::MSG_Input_Node(Independent_ID_Generator *Node_ID_Generator, Independent_ID_Generator *Connector_ID_Generator, ImVec2 initial_position) : Abs_Node(Node_ID_Generator, Connector_ID_Generator, NODE_TYPE_MSG_LINE_INPUT, initial_position) { // 判定是否成功申请ID if (this->id != -1) { // 消息输出节点 this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); } } // 绘制节点 void MSG_Input_Node::Show(void) { // auto ImNodesStyle = ImNodes::GetStyle(); // auto ImGuiStyle = ImGui::GetStyle(); if (this->close_flag == true) return; // 初始化位置设定 if ((this->initial_position.x != 0) || (this->initial_position.y != 0)) { ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position); this->initial_position = ImVec2(0, 0); } // 绘制节点 ImNodes::BeginNode(this->id); { // 标题部分 ImNodes::BeginNodeTitleBar(); { ImGui::Text(u8"DLT-信息输入节点"); ImGui::SameLine(); { ImGui::TextDisabled(u8"(?)"); // 上下边距为调整 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f)); if (ImGui::BeginItemTooltip()) { ImGui::Text("Node ID : %d\n", this->id); ImGui::Separator(); ImGui::Text(u8"每个处理流程开始时,输出一条DLT消息;\n每个此类节点输出的消息均会独立遍历所有输入文件;"); ImGui::EndTooltip(); } ImGui::PopStyleVar(); } ImGui::SameLine(); // ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize(u8"DLT-信息输入节点").x - ImGui::GetTextLineHeight(), 0.0f)); // 节点宽度调整 ImGui::Dummy(ImVec2(20.0f, 0.0f)); ImGui::SameLine(); // 绘制关闭按钮 if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2)) this->close_flag = true; } ImNodes::EndNodeTitleBar(); // 节点主体部分 { } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); ImVec2 text_size = ImGui::CalcTextSize(u8"OUT ->"); if (dimension.x > text_size.x) { ImGui::Dummy(ImVec2(dimension.x - text_size.x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f)); ImGui::SameLine(); } ImGui::Text(u8"OUT ->"); ImGui::SameLine(); /** * @todo 自定义接口绘制 */ for (auto Connector : this->Connector_List) { Connector->Show(); } ImGui::PopStyleVar(); } ImNodes::EndNode(); } // 执行处理流程 bool MSG_Input_Node::Execute_Process(void) { return true; };