Implemented the functions of saving the workspace into a json file and loading from it.

This commit is contained in:
LuChiChick 2026-04-23 20:23:09 +08:00
parent 07ee870601
commit e0afc4963f
2 changed files with 236 additions and 1 deletions

View File

@ -63,8 +63,11 @@ public:
// 清除工作路由 true -> success / false -> failed // 清除工作路由 true -> success / false -> failed
bool Clear_Process_Route(void); bool Clear_Process_Route(void);
// 清除整个工作区
void Clear_All(void);
// 加载取配置文件 true -> success / false -> failed // 加载取配置文件 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 // 存储配置文件 true -> success / false -> failed
bool Store_Config(const char *file_path); bool Store_Config(const char *file_path);

View File

@ -1,6 +1,7 @@
#include "Workflow_Editor.hpp" #include "Workflow_Editor.hpp"
#include "imgui_internal.h" #include "imgui_internal.h"
#include "Global_Variables.hpp" #include "Global_Variables.hpp"
#include "Json_Utilities.hpp"
extern "C" extern "C"
{ {
@ -15,6 +16,9 @@ void Workflow_Editor::Show(void)
int bounding_box_link_nums = ImNodes::NumSelectedLinks(); int bounding_box_link_nums = ImNodes::NumSelectedLinks();
int bounding_box_node_nums = ImNodes::NumSelectedNodes(); int bounding_box_node_nums = ImNodes::NumSelectedNodes();
// 加载配置文件标志位
bool Config_Load_Flag = false;
// 浅色主题节点编辑器窗体 // 浅色主题节点编辑器窗体
ImNodes::StyleColorsLight(); ImNodes::StyleColorsLight();
ImNodes::BeginNodeEditor(); ImNodes::BeginNodeEditor();
@ -69,6 +73,12 @@ void Workflow_Editor::Show(void)
if (this->Build_Process_Route() == false) if (this->Build_Process_Route() == false)
MessageBoxW(Main_Window_hWnd, L"构建工作树失败\n检查是否有合法的起始节点", L"", MB_OK | MB_ICONERROR); 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::EndPopup();
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -83,6 +93,10 @@ void Workflow_Editor::Show(void)
} }
ImNodes::EndNodeEditor(); ImNodes::EndNodeEditor();
// 处理配置文件加载
if (Config_Load_Flag == true)
this->Load_Config("[Debug]Config.Json", ImGui::GetMousePos());
// 处理连线 // 处理连线
{ {
int source_id = -1, target_id = -1; int source_id = -1, target_id = -1;
@ -583,3 +597,221 @@ bool Workflow_Editor::Clear_Process_Route(void)
this->Process_Route.swap(empty_route); this->Process_Route.swap(empty_route);
return true; 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<Json_Value> Node_Info_List;
std::vector<Json_Value> Link_Info_List;
// 工具Lambda表达式查找接口id的所属节点
auto Lambda_Find_Owner = [&](int connector_id) -> std::shared_ptr<Abs_Node>
{
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;
}