diff --git a/Inc/Nodes_And_Connectors.hpp b/Inc/Nodes_And_Connectors.hpp index 72e454a..4abeebd 100644 --- a/Inc/Nodes_And_Connectors.hpp +++ b/Inc/Nodes_And_Connectors.hpp @@ -67,7 +67,7 @@ public: * @param count 当前包位置 * @param total_count 包流总长度 */ - virtual bool Register_Package(void *p_content, size_t content_size, size_t count, size_t total_count); + virtual bool Register_Package(const void *p_content, size_t content_size, size_t count, size_t total_count); // 获取包 virtual const Package Get_Package(void); @@ -99,6 +99,9 @@ public: NODE_TYPE_CONNECTOR_TEST, // 接口测试节点 NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点 NODE_TYPE_FILTER, // 筛选器节点 + NODE_TYPE_LOGIC_AND, // 逻辑与门节点 + NODE_TYPE_LOGIC_OR, // 逻辑或门节点 + NODE_TYPE_LOGIC_NOT, // 逻辑非门节点 NODE_TYPE_CSV_EXPORTER, // CSV输出节点 } Node_Type_Enum; // 节点类型枚举 @@ -303,4 +306,70 @@ public: virtual bool Execute_Process(void); }; +// 逻辑与门 +class Logic_AND_Node : public Abs_Node +{ +private: + float node_width = 0; + +public: + // 显式禁用默认构造 + Logic_AND_Node() = delete; + + // 必要构造 + Logic_AND_Node(Independent_ID_Generator *Node_ID_Generator, + Independent_ID_Generator *Connector_ID_Generator, + ImVec2 initial_position = ImVec2(0, 0)); + + // 绘制节点 + virtual void Show(void); + + // 执行处理流程 + virtual bool Execute_Process(void); +}; + +// 逻辑与门 +class Logic_OR_Node : public Abs_Node +{ +private: + float node_width = 0; + +public: + // 显式禁用默认构造 + Logic_OR_Node() = delete; + + // 必要构造 + Logic_OR_Node(Independent_ID_Generator *Node_ID_Generator, + Independent_ID_Generator *Connector_ID_Generator, + ImVec2 initial_position = ImVec2(0, 0)); + + // 绘制节点 + virtual void Show(void); + + // 执行处理流程 + virtual bool Execute_Process(void); +}; + +// 逻辑与门 +class Logic_NOT_Node : public Abs_Node +{ +private: + float node_width = 0; + +public: + // 显式禁用默认构造 + Logic_NOT_Node() = delete; + + // 必要构造 + Logic_NOT_Node(Independent_ID_Generator *Node_ID_Generator, + Independent_ID_Generator *Connector_ID_Generator, + ImVec2 initial_position = ImVec2(0, 0)); + + // 绘制节点 + virtual void Show(void); + + // 执行处理流程 + virtual bool Execute_Process(void); +}; + #endif \ No newline at end of file diff --git a/Src/Nodes_And_Connectors.cpp b/Src/Nodes_And_Connectors.cpp index b140360..305c502 100644 --- a/Src/Nodes_And_Connectors.cpp +++ b/Src/Nodes_And_Connectors.cpp @@ -165,7 +165,7 @@ bool Abs_Connector::Disconnect_To(Abs_Connector *target) * @param count 当前包位置 * @param total_count 包流总长度 */ -bool Abs_Connector::Register_Package(void *p_content, size_t content_size, size_t count, size_t total_count) +bool Abs_Connector::Register_Package(const void *p_content, size_t content_size, size_t count, size_t total_count) { // 非输出类接口 if (this->type != CONNECTOR_TYPE_OUTPUT) @@ -708,10 +708,11 @@ bool MSG_Input_Node::Execute_Process(void) if (this->private_excute_count < this->private_excute_end_count) { // [0] -> MSG - this->Connector_List[0]->Register_Package((void *)&(this->log.msg_list[this->private_excute_count]), - sizeof(this->log.msg_list[0]), - this->private_excute_count + 1, - this->excute_end_count); + if (this->Connector_List[0]->Register_Package(&(this->log.msg_list[this->private_excute_count]), + sizeof(this->log.msg_list[0]), + this->private_excute_count + 1, + this->excute_end_count) == false) + return false; this->private_excute_count++; } else @@ -738,10 +739,10 @@ Filter_Node::Filter_Node(Independent_ID_Generator *Node_ID_Generator, // 判定是否成功申请ID if (this->id != -1) { - // Boolean 输入节点 + // Boolean 相关接口 this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [0] -> Boolean - // 消息输出节点 + // DLT MSG 相关接口 this->Connector_List.push_back(std::make_shared(Connector_ID_Generator, true)); // [1] -> MSG this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [2] MSG -> } @@ -882,12 +883,419 @@ bool Filter_Node::Execute_Process(void) if (pass_allow) { auto pkg = this->Connector_List[1]->Get_Package(); - this->Connector_List[2]->Register_Package(pkg.p_content_mem, pkg.content_size, pkg.package_count, pkg.total_count); + return this->Connector_List[2]->Register_Package(pkg.p_content_mem, pkg.content_size, pkg.package_count, pkg.total_count); } - else - this->Connector_List[2]->Register_Package(nullptr, 0, 0, 0); - return true; + return this->Connector_List[2]->Register_Package(nullptr, 0, 0, 0); +} + +// 必要构造 +Logic_AND_Node::Logic_AND_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_LOGIC_AND, + initial_position) +{ + // 判定是否成功申请ID + if (this->id != -1) + { + // Boolean 相关接口 + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [0] -> Boolean + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [1] Boolean -> + } +} + +// 绘制节点 +void Logic_AND_Node::Show(void) +{ + 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); + } + + // 全宽适配 + bool all_width_fit = true; + + // 绘制节点 + ImNodes::BeginNode(this->id); + { + + // 获取节点当前长宽维度 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + + // 标题部分 + ImNodes::BeginNodeTitleBar(); + { + const char *title_str = u8"Logic AND"; + + ImGui::Text(title_str); + 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"逻辑与门,对输入逻辑状态进行与运算"); + ImGui::EndTooltip(); + } + + ImGui::PopStyleVar(); + } + ImGui::SameLine(); + + // 节点宽度调整 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + auto button_diameter = ImGui::GetTextLineHeight(); + auto text_width = ImGui::CalcTextSize(title_str).x + ImGui::CalcTextSize(u8"(?)").x; + auto Tittle_Str_Width = text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::GetStyle().ItemSpacing.x * 2; + + // 宽度判定 + if (dimension.x < Tittle_Str_Width + button_diameter + ImGui::GetStyle().ItemSpacing.x) + all_width_fit = false; + + ImGui::Dummy(ImVec2(this->node_width - Tittle_Str_Width - button_diameter - ImGui::GetStyle().ItemSpacing.x, 0.0f)); + ImGui::SameLine(); + + // 绘制关闭按钮 + if (CircleButtonWithX("#X", button_diameter / 2)) + this->close_flag = true; + } + ImNodes::EndNodeTitleBar(); + + // 节点主体部分 + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); + + // 绘制 Boolean 相关接口组 + { + // 宽度判定 + auto text_width = ImGui::CalcTextSize("-> Boolean-In").x + ImGui::CalcTextSize("Boolean-Out ->").x; + if (dimension.x < text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::CalcTextSize("A").x) + all_width_fit = false; + + // 宽度初始化 + if (this->node_width == 0) + this->node_width = text_width; + + this->Connector_List[0]->Show(); + ImGui::SameLine(); + ImGui::Text("-> Boolean-In"); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(this->node_width - text_width - ImNodes::GetStyle().NodePadding.x * 2, 0.0f)); + ImGui::SameLine(); + ImGui::Text("Boolean-Out ->"); + ImGui::SameLine(); + this->Connector_List[1]->Show(); + } + + ImGui::PopStyleVar(); + } + + // 使用递进的方式自适应宽度 + if (all_width_fit == false) + this->node_width += 1.0f; + } + ImNodes::EndNode(); +} + +// 执行处理流程 +bool Logic_AND_Node::Execute_Process(void) +{ + bool out_logic = true; + for (auto connector : this->Connector_List[0]->Get_Related_List()) + { + auto pkg = connector->Get_Package(); + if ((pkg.content_size == 0) || (*((const bool *)pkg.p_content_mem) == false)) + { + out_logic = false; + break; + } + } + return this->Connector_List[1]->Register_Package(&out_logic, sizeof(out_logic), 0, 0); +} + +// 必要构造 +Logic_OR_Node::Logic_OR_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_LOGIC_OR, + initial_position) +{ + // 判定是否成功申请ID + if (this->id != -1) + { + // Boolean 相关接口 + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [0] -> Boolean + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [1] Boolean -> + } +} + +// 绘制节点 +void Logic_OR_Node::Show(void) +{ + 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); + } + + // 全宽适配 + bool all_width_fit = true; + + // 绘制节点 + ImNodes::BeginNode(this->id); + { + + // 获取节点当前长宽维度 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + + // 标题部分 + ImNodes::BeginNodeTitleBar(); + { + const char *title_str = u8"Logic OR"; + + ImGui::Text(title_str); + 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"逻辑或门,对输入逻辑状态进行或运算"); + ImGui::EndTooltip(); + } + + ImGui::PopStyleVar(); + } + ImGui::SameLine(); + + // 节点宽度调整 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + auto button_diameter = ImGui::GetTextLineHeight(); + auto text_width = ImGui::CalcTextSize(title_str).x + ImGui::CalcTextSize(u8"(?)").x; + auto Tittle_Str_Width = text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::GetStyle().ItemSpacing.x * 2; + + // 宽度判定 + if (dimension.x < Tittle_Str_Width + button_diameter + ImGui::GetStyle().ItemSpacing.x) + all_width_fit = false; + + ImGui::Dummy(ImVec2(this->node_width - Tittle_Str_Width - button_diameter - ImGui::GetStyle().ItemSpacing.x, 0.0f)); + ImGui::SameLine(); + + // 绘制关闭按钮 + if (CircleButtonWithX("#X", button_diameter / 2)) + this->close_flag = true; + } + ImNodes::EndNodeTitleBar(); + + // 节点主体部分 + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); + + // 绘制 Boolean 相关接口组 + { + // 宽度判定 + auto text_width = ImGui::CalcTextSize("-> Boolean-In").x + ImGui::CalcTextSize("Boolean-Out ->").x; + if (dimension.x < text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::CalcTextSize("A").x) + all_width_fit = false; + + // 宽度初始化 + if (this->node_width == 0) + this->node_width = text_width; + + this->Connector_List[0]->Show(); + ImGui::SameLine(); + ImGui::Text("-> Boolean-In"); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(this->node_width - text_width - ImNodes::GetStyle().NodePadding.x * 2, 0.0f)); + ImGui::SameLine(); + ImGui::Text("Boolean-Out ->"); + ImGui::SameLine(); + this->Connector_List[1]->Show(); + } + + ImGui::PopStyleVar(); + } + + // 使用递进的方式自适应宽度 + if (all_width_fit == false) + this->node_width += 1.0f; + } + ImNodes::EndNode(); +} + +// 执行处理流程 +bool Logic_OR_Node::Execute_Process(void) +{ + bool out_logic = false; + for (auto connector : this->Connector_List[0]->Get_Related_List()) + { + auto pkg = connector->Get_Package(); + if ((pkg.content_size > 0) && (*((const bool *)pkg.p_content_mem) == true)) + { + out_logic = true; + break; + } + } + + return this->Connector_List[1]->Register_Package(&out_logic, sizeof(out_logic), 0, 0); +} + +// 必要构造 +Logic_NOT_Node::Logic_NOT_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_LOGIC_NOT, + initial_position) +{ + // 判定是否成功申请ID + if (this->id != -1) + { + // Boolean 相关接口 + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator, true)); // [0] -> Boolean + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [1] Boolean -> + } +} + +// 绘制节点 +void Logic_NOT_Node::Show(void) +{ + 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); + } + + // 全宽适配 + bool all_width_fit = true; + + // 绘制节点 + ImNodes::BeginNode(this->id); + { + + // 获取节点当前长宽维度 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + + // 标题部分 + ImNodes::BeginNodeTitleBar(); + { + const char *title_str = u8"Logic NOT"; + + ImGui::Text(title_str); + 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"逻辑非门,对输入逻辑状态进行非运算"); + ImGui::EndTooltip(); + } + + ImGui::PopStyleVar(); + } + ImGui::SameLine(); + + // 节点宽度调整 + ImVec2 dimension = ImNodes::GetNodeDimensions(this->id); + auto button_diameter = ImGui::GetTextLineHeight(); + auto text_width = ImGui::CalcTextSize(title_str).x + ImGui::CalcTextSize(u8"(?)").x; + auto Tittle_Str_Width = text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::GetStyle().ItemSpacing.x * 2; + + // 宽度判定 + if (dimension.x < Tittle_Str_Width + button_diameter + ImGui::GetStyle().ItemSpacing.x) + all_width_fit = false; + + ImGui::Dummy(ImVec2(this->node_width - Tittle_Str_Width - button_diameter - ImGui::GetStyle().ItemSpacing.x, 0.0f)); + ImGui::SameLine(); + + // 绘制关闭按钮 + if (CircleButtonWithX("#X", button_diameter / 2)) + this->close_flag = true; + } + ImNodes::EndNodeTitleBar(); + + // 节点主体部分 + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); + + // 绘制 Boolean 相关接口组 + { + // 宽度判定 + auto text_width = ImGui::CalcTextSize("-> Boolean-In").x + ImGui::CalcTextSize("Boolean-Out ->").x; + if (dimension.x < text_width + ImNodes::GetStyle().NodePadding.x * 2 + ImGui::CalcTextSize("A").x) + all_width_fit = false; + + // 宽度初始化 + if (this->node_width == 0) + this->node_width = text_width; + + this->Connector_List[0]->Show(); + ImGui::SameLine(); + ImGui::Text("-> Boolean-In"); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(this->node_width - text_width - ImNodes::GetStyle().NodePadding.x * 2, 0.0f)); + ImGui::SameLine(); + ImGui::Text("Boolean-Out ->"); + ImGui::SameLine(); + this->Connector_List[1]->Show(); + } + + ImGui::PopStyleVar(); + } + + // 使用递进的方式自适应宽度 + if (all_width_fit == false) + this->node_width += 1.0f; + } + ImNodes::EndNode(); +} + +// 执行处理流程 +bool Logic_NOT_Node::Execute_Process(void) +{ + auto pkg = this->Connector_List[0]->Get_Related_List()[0]->Get_Package(); + bool out_logic; + + if (pkg.content_size == 0 || ((*(bool *)pkg.p_content_mem) == false)) + out_logic = false; + else + out_logic = true; + + out_logic = !out_logic; + + return this->Connector_List[1]->Register_Package(&out_logic, sizeof(out_logic), 0, 0); } // END \ No newline at end of file diff --git a/Src/Workflow_Editor.cpp b/Src/Workflow_Editor.cpp index aa84526..d238800 100644 --- a/Src/Workflow_Editor.cpp +++ b/Src/Workflow_Editor.cpp @@ -65,6 +65,20 @@ void Workflow_Editor::Show(void) this->Add_Node(Abs_Node::NODE_TYPE_MSG_LINE_INPUT, click_pos); if (ImGui::MenuItem(u8"消息筛选器")) this->Add_Node(Abs_Node::NODE_TYPE_FILTER, click_pos); + + // 逻辑门节点 + if (ImGui::BeginMenu(u8"逻辑门节点")) + { + if (ImGui::MenuItem(u8"AND")) + this->Add_Node(Abs_Node::NODE_TYPE_LOGIC_AND, click_pos); + if (ImGui::MenuItem(u8"OR")) + this->Add_Node(Abs_Node::NODE_TYPE_LOGIC_OR, click_pos); + if (ImGui::MenuItem(u8"NOT")) + this->Add_Node(Abs_Node::NODE_TYPE_LOGIC_NOT, click_pos); + + ImGui::EndMenu(); + } + ImGui::EndMenu(); } @@ -278,7 +292,27 @@ bool Workflow_Editor::Add_Node(Abs_Node::Node_Type_Enum type, ImVec2 initial_pos &this->Connector_ID_Generator, initial_position); break; + case Abs_Node::NODE_TYPE_LOGIC_AND: // 逻辑与门节点 + // 创建节点 + p_New_Node = std::make_shared(&this->Node_ID_Generator, + &this->Connector_ID_Generator, + initial_position); + break; + case Abs_Node::NODE_TYPE_LOGIC_OR: // 逻辑或门节点 + + // 创建节点 + p_New_Node = std::make_shared(&this->Node_ID_Generator, + &this->Connector_ID_Generator, + initial_position); + break; + case Abs_Node::NODE_TYPE_LOGIC_NOT: // 逻辑非门节点 + + // 创建节点 + p_New_Node = std::make_shared(&this->Node_ID_Generator, + &this->Connector_ID_Generator, + initial_position); + break; case Abs_Node::NODE_TYPE_CSV_EXPORTER: // CSV输出器 break; default: