From e0afc4963f6d117689fcca0efc814c6654c68861 Mon Sep 17 00:00:00 2001 From: LuChiChick <1084116302@qq.com> Date: Thu, 23 Apr 2026 20:23:09 +0800 Subject: [PATCH] Implemented the functions of saving the workspace into a json file and loading from it. --- Inc/Workflow_Editor.hpp | 5 +- Src/Workflow_Editor.cpp | 232 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 1 deletion(-) diff --git a/Inc/Workflow_Editor.hpp b/Inc/Workflow_Editor.hpp index 332abe8..ad09ace 100644 --- a/Inc/Workflow_Editor.hpp +++ b/Inc/Workflow_Editor.hpp @@ -63,8 +63,11 @@ public: // 清除工作路由 true -> success / false -> failed bool Clear_Process_Route(void); + // 清除整个工作区 + void Clear_All(void); + // 加载取配置文件 true -> success / false -> failed - bool Load_Config(const char *file_path); + bool Load_Config(const char *file_path, ImVec2 initial_position = ImVec2(0, 0)); // 存储配置文件 true -> success / false -> failed bool Store_Config(const char *file_path); diff --git a/Src/Workflow_Editor.cpp b/Src/Workflow_Editor.cpp index 9e1e796..d7ff68d 100644 --- a/Src/Workflow_Editor.cpp +++ b/Src/Workflow_Editor.cpp @@ -1,6 +1,7 @@ #include "Workflow_Editor.hpp" #include "imgui_internal.h" #include "Global_Variables.hpp" +#include "Json_Utilities.hpp" extern "C" { @@ -15,6 +16,9 @@ void Workflow_Editor::Show(void) int bounding_box_link_nums = ImNodes::NumSelectedLinks(); int bounding_box_node_nums = ImNodes::NumSelectedNodes(); + // 加载配置文件标志位 + bool Config_Load_Flag = false; + // 浅色主题节点编辑器窗体 ImNodes::StyleColorsLight(); ImNodes::BeginNodeEditor(); @@ -69,6 +73,12 @@ void Workflow_Editor::Show(void) if (this->Build_Process_Route() == false) MessageBoxW(Main_Window_hWnd, L"构建工作树失败\n检查是否有合法的起始节点", L"", MB_OK | MB_ICONERROR); + if (ImGui::MenuItem(u8"存储工作区(Debug)")) + this->Store_Config("[Debug]Config.Json"); + + if (ImGui::MenuItem(u8"加载工作区(Debug)")) + Config_Load_Flag = true; + ImGui::EndPopup(); } ImGui::PopStyleVar(); @@ -83,6 +93,10 @@ void Workflow_Editor::Show(void) } ImNodes::EndNodeEditor(); + // 处理配置文件加载 + if (Config_Load_Flag == true) + this->Load_Config("[Debug]Config.Json", ImGui::GetMousePos()); + // 处理连线 { int source_id = -1, target_id = -1; @@ -581,5 +595,223 @@ bool Workflow_Editor::Clear_Process_Route(void) { decltype(this->Process_Route) empty_route; this->Process_Route.swap(empty_route); + return true; +} + +// 清除整个工作区 +void Workflow_Editor::Clear_All(void) +{ + for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++) + iterator = this->Del_Node(iterator) - 1; + this->Clear_Process_Route(); +} + +// 加载取配置文件 true -> success / false -> failed +bool Workflow_Editor::Load_Config(const char *file_path, ImVec2 initial_position) +{ + // 工具Lambda string 转 wstring + auto Lambda_String_To_WString = [](const std::string &str) -> std::wstring + { + if (str.empty()) + return std::wstring(); + int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0); + if (len <= 0) + return std::wstring(); + std::wstring wstr(len, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], len); + return wstr; + }; + + Json_Value Config_Value; + std::string err_str = JsonFile_Parse(file_path, &Config_Value); + + if (!err_str.empty()) + { + MessageBoxW(Main_Window_hWnd, (L"文件解析错误!!\n" + Lambda_String_To_WString(err_str)).c_str(), L"", MB_OK | MB_ICONERROR); + return false; + } + + // 清理工作区 + this->Clear_All(); + decltype(this->Node_Pool) Created_Node_List; + + // 创建节点 + { + auto Node_Info_List = Config_Value.asObject().get("Nodes").asArry().element_list; + + // 计算中心坐标 + ImVec2 Position_Offset = {0, 0}; + for (auto Node_Info : Node_Info_List) + { + Position_Offset.x += Node_Info.asObject().get("position").asObject().get("x").asFloat(); + Position_Offset.y += Node_Info.asObject().get("position").asObject().get("y").asFloat(); + } + if (Node_Info_List.size() > 0) + { + Position_Offset.x /= Node_Info_List.size(); + Position_Offset.y /= Node_Info_List.size(); + } + + // 计算与初始位置的偏移量 + Position_Offset.x = initial_position.x - Position_Offset.x; + Position_Offset.y = initial_position.y - Position_Offset.y; + + // 依次新建节点 + for (auto Node_Info : Node_Info_List) + { + + this->Add_Node((Abs_Node::Node_Type_Enum)Node_Info.asObject().get("type").asInteger(), + ImVec2(Node_Info.asObject().get("position").asObject().get("x").asFloat() + Position_Offset.x, + Node_Info.asObject().get("position").asObject().get("y").asFloat() + Position_Offset.y)); + + Created_Node_List.push_back(this->Node_Pool.back()); + } + } + + // 创建连接关系 + { + auto Link_Info_List = Config_Value.asObject().get("Connections").asArry().element_list; + for (auto Link_Info : Link_Info_List) + { + auto Source_Info = Link_Info.asObject().get("source").asObject(); + auto Target_Info = Link_Info.asObject().get("target").asObject(); + + auto Source_Connector = Created_Node_List[Source_Info.get("owner").asInteger()]->Get_Connector_List()[Source_Info.get("index").asInteger()]; + auto Target_Connector = Created_Node_List[Target_Info.get("owner").asInteger()]->Get_Connector_List()[Target_Info.get("index").asInteger()]; + + this->Add_Link(Source_Connector->Get_ID(), Target_Connector->Get_ID()); + } + } + + return true; +} + +// 存储配置文件 true -> success / false -> failed +bool Workflow_Editor::Store_Config(const char *file_path) +{ + FILE *pFile = fopen(file_path, "wb"); + if (pFile == nullptr) + { + MessageBoxW(Main_Window_hWnd, L"文件打开失败!!", L"", MB_OK | MB_ICONERROR); + return false; + } + fclose(pFile); + + std::vector Node_Info_List; + std::vector Link_Info_List; + + // 工具Lambda表达式,查找接口id的所属节点 + auto Lambda_Find_Owner = [&](int connector_id) -> std::shared_ptr + { + for (auto pNode : this->Node_Pool) + { + for (auto pConnector : pNode->Get_Connector_List()) + { + if (pConnector->Get_ID() == connector_id) + return pNode; + } + } + + return nullptr; + }; + + // 遍历节点池,以遍历计数作为存储相对序列索引 + size_t Node_Count = this->Node_Pool.size(); + for (size_t node_index = 0; node_index < Node_Count; node_index++) + { + // 存储节点相关信息 + ImVec2 position = ImNodes::GetNodeGridSpacePos(this->Node_Pool[node_index]->Get_ID()); + Node_Info_List.push_back( + Json_Object({{"index", (int)node_index}, // + {"type", this->Node_Pool[node_index]->Get_Type()}, // + { + "position", Json_Object({ + {"x", position.x}, // + {"y", position.y} // + }) // + }, // + {"args", Json_Arry()}} // + )); + + // 查询是有相关联的连接 + for (auto edge : this->Edge_Pool) + { + // 存在关联连接时 + if (Lambda_Find_Owner(edge.source_connector_id) == this->Node_Pool[node_index]) + { + int target_node_index = -1; // 目标节点索引 + int source_connector_index = -1; // 源接口索引 + int target_connector_index = -1; // 目标接口索引 + + // 查询源接口在源节点的索引 + size_t list_size = this->Node_Pool[node_index]->Get_Connector_List().size(); + for (size_t count = 0; count < list_size; count++) + if (this->Node_Pool[node_index]->Get_Connector_List()[count]->Get_ID() == edge.source_connector_id) + { + source_connector_index = count; + break; + } + + // 查询目标节点索引 + auto pTarget_Node = Lambda_Find_Owner(edge.target_connector_id); + for (size_t count = 0; count < Node_Count; count++) + if (this->Node_Pool[count] == pTarget_Node) + { + target_node_index = count; + break; + } + + // 查询目标接口在目标节点的索引 + list_size = pTarget_Node->Get_Connector_List().size(); + for (size_t count = 0; count < list_size; count++) + if (pTarget_Node->Get_Connector_List()[count]->Get_ID() == edge.target_connector_id) + { + target_connector_index = count; + break; + } + + Link_Info_List.push_back( + Json_Object( + { + {"source", Json_Object({ + {"owner", (int)node_index}, // + {"index", source_connector_index}, // + })}, // + {"target", Json_Object({ + {"owner", target_node_index}, // + {"index", target_connector_index}, // + })} // + })); + } + } + } + + std::string err_str = Json_Export(file_path, + Json_Object({ + {"Nodes", Json_Arry(Node_Info_List)}, // + {"Connections", Json_Arry(Link_Info_List)} // + }), + true); + + // 输出错误信息 + if (!err_str.empty()) + { + // 工具Lambda string 转 wstring + auto Lambda_String_To_WString = [](const std::string &str) -> std::wstring + { + if (str.empty()) + return std::wstring(); + int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0); + if (len <= 0) + return std::wstring(); + std::wstring wstr(len, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], len); + return wstr; + }; + + MessageBoxW(Main_Window_hWnd, (L"存储配置文件失败!!\n" + Lambda_String_To_WString(err_str)).c_str(), L"", MB_OK | MB_ICONERROR); + return false; + } + return true; } \ No newline at end of file