817 lines
30 KiB
C++
817 lines
30 KiB
C++
#include "Workflow_Editor.hpp"
|
||
#include "imgui_internal.h"
|
||
#include "Global_Variables.hpp"
|
||
#include "Json_Utilities.hpp"
|
||
|
||
extern "C"
|
||
{
|
||
#include "windows.h"
|
||
}
|
||
|
||
// 绘制节点编辑器
|
||
void Workflow_Editor::Show(void)
|
||
{
|
||
// 选区信息
|
||
bool bounding_box_delete_flag = false;
|
||
int bounding_box_link_nums = ImNodes::NumSelectedLinks();
|
||
int bounding_box_node_nums = ImNodes::NumSelectedNodes();
|
||
|
||
// 加载配置文件标志位
|
||
bool Config_Load_Flag = false;
|
||
|
||
// 浅色主题节点编辑器窗体
|
||
ImNodes::StyleColorsLight();
|
||
ImNodes::BeginNodeEditor();
|
||
{
|
||
// 显示所有节点
|
||
for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++)
|
||
{
|
||
if ((*iterator)->Get_CloseFlag() == true)
|
||
{
|
||
// 处理节点删除
|
||
iterator = this->Del_Node(iterator);
|
||
iterator--;
|
||
}
|
||
else
|
||
// 绘制节点
|
||
(*iterator)->Show();
|
||
}
|
||
|
||
// 右键菜单
|
||
{
|
||
const bool open_popup = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
|
||
ImNodes::IsEditorHovered() &&
|
||
ImGui::IsMouseReleased(ImGuiMouseButton_Right);
|
||
|
||
// 设置弹窗周边Padding
|
||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
|
||
|
||
// if (!ImGui::IsAnyItemHovered() && open_popup)
|
||
if (open_popup)
|
||
{
|
||
ImGui::OpenPopup("RightClick_Popup");
|
||
}
|
||
|
||
if (ImGui::BeginPopup("RightClick_Popup"))
|
||
{
|
||
ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup();
|
||
// 节点添加菜单
|
||
if (ImGui::BeginMenu(u8"创建节点"))
|
||
{
|
||
if (ImGui::MenuItem(u8"接口测试节点"))
|
||
this->Add_Node(Abs_Node::NODE_TYPE_CONNECTOR_TEST, click_pos);
|
||
if (ImGui::MenuItem(u8"DLT信息输入节点"))
|
||
this->Add_Node(Abs_Node::NODE_TYPE_MSG_LINE_INPUT, click_pos);
|
||
ImGui::EndMenu();
|
||
}
|
||
|
||
// 删除框选内容
|
||
if (ImGui::MenuItem(u8"删除所选内容", nullptr, nullptr, (bounding_box_link_nums > 0) || (bounding_box_node_nums > 0)))
|
||
bounding_box_delete_flag = true;
|
||
|
||
if (ImGui::MenuItem(u8"构建工作树(Debug)"))
|
||
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();
|
||
}
|
||
|
||
// 显示所有的连线
|
||
for (auto Edge : this->Edge_Pool)
|
||
ImNodes::Link(Edge.id, Edge.source_connector_id, Edge.target_connector_id);
|
||
|
||
// 缩略图
|
||
ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_TopRight);
|
||
}
|
||
ImNodes::EndNodeEditor();
|
||
|
||
// 处理配置文件加载
|
||
if (Config_Load_Flag == true)
|
||
this->Load_Config("[Debug]Config.Json", ImGui::GetMousePos());
|
||
|
||
// 处理连线
|
||
{
|
||
int source_id = -1, target_id = -1;
|
||
if (ImNodes::IsLinkCreated(&source_id, &target_id))
|
||
this->Add_Link(source_id, target_id);
|
||
}
|
||
|
||
// 处理键盘事件
|
||
{
|
||
// Ctrl + A 全选
|
||
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_A) == true)
|
||
{
|
||
for (auto Link : this->Edge_Pool)
|
||
if (ImNodes::IsLinkSelected(Link.id) == false)
|
||
ImNodes::SelectLink(Link.id);
|
||
for (auto pNode : this->Node_Pool)
|
||
if (ImNodes::IsNodeSelected(pNode->Get_ID()) == false)
|
||
ImNodes::SelectNode(pNode->Get_ID());
|
||
}
|
||
|
||
// Ctrl + X 剪切
|
||
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_X) == true)
|
||
{
|
||
bounding_box_delete_flag = true;
|
||
|
||
/**
|
||
* @todo
|
||
* 剪切板实现
|
||
*/
|
||
}
|
||
|
||
// Delete 按键释放 或有删除请求
|
||
if (ImGui::IsKeyReleased(ImGuiKey_Delete) || bounding_box_delete_flag)
|
||
{
|
||
// 释放所有选中的边
|
||
{
|
||
std::vector<int> target_edge_id_list;
|
||
target_edge_id_list.resize(ImNodes::NumSelectedLinks());
|
||
if (target_edge_id_list.size() > 0)
|
||
{
|
||
ImNodes::GetSelectedLinks(&target_edge_id_list[0]);
|
||
for (auto edge_iterator = this->Edge_Pool.begin(); edge_iterator != this->Edge_Pool.end(); edge_iterator++)
|
||
{
|
||
if (target_edge_id_list.size() > 0)
|
||
for (auto target_id_iterator = target_edge_id_list.begin(); target_id_iterator != target_edge_id_list.end(); target_id_iterator++)
|
||
{
|
||
if (*target_id_iterator == edge_iterator->id)
|
||
{
|
||
target_edge_id_list.erase(target_id_iterator);
|
||
edge_iterator = this->Del_Link(edge_iterator) - 1;
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 释放所有选中的节点
|
||
{
|
||
std::vector<int> target_id_list;
|
||
target_id_list.resize(ImNodes::NumSelectedNodes());
|
||
if (target_id_list.size() > 0)
|
||
ImNodes::GetSelectedNodes(&target_id_list[0]);
|
||
for (auto target_id : target_id_list)
|
||
this->Del_Node(target_id);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 新增节点 true -> success / false -> failed
|
||
bool Workflow_Editor::Add_Node(Abs_Node::Node_Type_Enum type, ImVec2 initial_position)
|
||
{
|
||
// 新节点
|
||
std::shared_ptr<Abs_Node> p_New_Node;
|
||
|
||
// 记录节点
|
||
switch (type)
|
||
{
|
||
|
||
case Abs_Node::NODE_TYPE_CONNECTOR_TEST: // 接口测试节点
|
||
p_New_Node = std::make_shared<Connector_Test_Node>(&this->Node_ID_Generator,
|
||
&this->Connector_ID_Generator,
|
||
initial_position);
|
||
break;
|
||
case Abs_Node::NODE_TYPE_MSG_LINE_INPUT: // 消息行输入 (头节点)
|
||
|
||
// 创建节点
|
||
p_New_Node = std::make_shared<MSG_Input_Node>(&this->Node_ID_Generator,
|
||
&this->Connector_ID_Generator,
|
||
initial_position);
|
||
break;
|
||
|
||
case Abs_Node::NODE_TYPE_CSV_EXPORTER: // CSV输出器
|
||
break;
|
||
default:
|
||
return false;
|
||
}
|
||
|
||
// 成功分配时
|
||
if (p_New_Node.get() != nullptr)
|
||
{
|
||
// 将新增的节点记录到接口池及散点池
|
||
this->Node_Pool.push_back(p_New_Node);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 删除节点 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用
|
||
std::vector<std::shared_ptr<Abs_Node>>::iterator Workflow_Editor::Del_Node(std::vector<std::shared_ptr<Abs_Node>>::iterator iterator)
|
||
{
|
||
// 获取接口列表
|
||
auto Connector_List = (*iterator)->Get_Connector_List();
|
||
|
||
// 删除列表中所有与该节点接口相关的边并从接口池中删除
|
||
for (auto pConnector : Connector_List)
|
||
{
|
||
int connector_id = pConnector->Get_ID();
|
||
// 遍历边池
|
||
for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++)
|
||
{
|
||
if ((iterator->source_connector_id == connector_id) || (iterator->target_connector_id == connector_id))
|
||
{
|
||
// 注销边ID
|
||
this->Edge_ID_Generator.Release_ID(connector_id);
|
||
// 注销边记录,迭代器删除后会返回下一个位置的迭代器
|
||
iterator = this->Edge_Pool.erase(iterator) - 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
iterator = this->Node_Pool.erase(iterator);
|
||
|
||
return iterator;
|
||
}
|
||
|
||
// 删除节点 true -> success / false -> failed
|
||
bool Workflow_Editor::Del_Node(int target_node_id)
|
||
{
|
||
// 查找ID
|
||
for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++)
|
||
{
|
||
// 从节点池删除对应的节点
|
||
if ((*iterator)->Get_ID() == target_node_id)
|
||
{
|
||
this->Del_Node(iterator);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// 未成功查找
|
||
return false;
|
||
}
|
||
|
||
// 新增连接 true -> success / false -> failed
|
||
bool Workflow_Editor::Add_Link(int source_connector_id, int target_connector_id)
|
||
{
|
||
// 查找接口
|
||
bool find = false;
|
||
std::shared_ptr<Abs_Connector> p_source_connector;
|
||
std::shared_ptr<Abs_Connector> p_target_connector;
|
||
for (auto pNode : this->Node_Pool)
|
||
{
|
||
for (auto pConnector : pNode->Get_Connector_List())
|
||
{
|
||
if (pConnector->Get_ID() == source_connector_id)
|
||
p_source_connector = pConnector;
|
||
if (pConnector->Get_ID() == target_connector_id)
|
||
p_target_connector = pConnector;
|
||
if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr))
|
||
{
|
||
find = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (find)
|
||
break;
|
||
}
|
||
|
||
// 判定查找结果
|
||
if (find)
|
||
{
|
||
// 检查下一步的连接是否会出现回环
|
||
{
|
||
// 工具Lambda表达式,查找接口id的所属节点
|
||
auto Lambda_Find_Owner = [&](int connector_id) -> Abs_Node *
|
||
{
|
||
for (auto pNode : this->Node_Pool)
|
||
{
|
||
for (auto pConnector : pNode->Get_Connector_List())
|
||
{
|
||
if (pConnector->Get_ID() == connector_id)
|
||
return pNode.get();
|
||
}
|
||
}
|
||
|
||
return nullptr;
|
||
};
|
||
|
||
// 关联关系查找(递归Lambda)
|
||
auto Lambda_Find_Related = [&](auto self, Abs_Node *pSource, Abs_Node *pTarget) -> bool
|
||
{
|
||
std::vector<Abs_Node *> Sub_Node_List;
|
||
for (auto pConnector : pSource->Get_Connector_List())
|
||
{
|
||
// 检索所有OutPut类型的接口的下位节点
|
||
if (pConnector->Get_Type() == Abs_Connector::CONNECTOR_TYPE_OUTPUT)
|
||
{
|
||
for (auto pSubConnector : pConnector->Get_Related_List())
|
||
{
|
||
auto pSubNode = Lambda_Find_Owner(pSubConnector->Get_ID());
|
||
bool duplicated = false;
|
||
|
||
// 查重并加入子节点列表
|
||
for (auto pNode : Sub_Node_List)
|
||
{
|
||
if (pNode == pSubNode)
|
||
{
|
||
duplicated = true;
|
||
break;
|
||
}
|
||
}
|
||
if (!duplicated)
|
||
Sub_Node_List.push_back(pSubNode);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 递归出口 无子节点时直接返回
|
||
if (Sub_Node_List.size() == 0)
|
||
return false;
|
||
|
||
// 检索所有的下位节点
|
||
for (auto pNode : Sub_Node_List)
|
||
{
|
||
if (pNode == pTarget)
|
||
return true;
|
||
else if (self(self, pNode, pTarget) == true)
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
};
|
||
|
||
// 检查连接关系
|
||
if (Lambda_Find_Related(Lambda_Find_Related, Lambda_Find_Owner(target_connector_id), Lambda_Find_Owner(source_connector_id)))
|
||
{
|
||
MessageBoxW(Main_Window_hWnd, L"存在回环连线!!!", L"", MB_OK | MB_ICONERROR);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 先尝试连接,成功后再进行边池操作
|
||
if (p_source_connector->Connect_To(p_target_connector.get()) == true)
|
||
{
|
||
// 记录到边池
|
||
this->Edge_Pool.push_back({this->Edge_ID_Generator.Request_ID(), source_connector_id, target_connector_id});
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 删除边 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用
|
||
std::vector<Workflow_Editor::Edge>::iterator Workflow_Editor::Del_Link(std::vector<Edge>::iterator iterator)
|
||
{
|
||
// 查找接口
|
||
bool find = false;
|
||
std::shared_ptr<Abs_Connector> p_source_connector;
|
||
std::shared_ptr<Abs_Connector> p_target_connector;
|
||
for (auto pNode : this->Node_Pool)
|
||
{
|
||
for (auto pConnector : pNode->Get_Connector_List())
|
||
{
|
||
if (pConnector->Get_ID() == iterator->source_connector_id)
|
||
p_source_connector = pConnector;
|
||
if (pConnector->Get_ID() == iterator->target_connector_id)
|
||
p_target_connector = pConnector;
|
||
if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr))
|
||
{
|
||
find = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (find)
|
||
break;
|
||
}
|
||
|
||
// 判定查找结果
|
||
if (find)
|
||
{
|
||
// 成功删除连接关系
|
||
if (p_source_connector->Disconnect_To(p_target_connector.get()) == true)
|
||
{
|
||
// 释放ID并销毁容器
|
||
this->Edge_ID_Generator.Release_ID(iterator->id);
|
||
return this->Edge_Pool.erase(iterator);
|
||
}
|
||
}
|
||
|
||
return iterator--;
|
||
}
|
||
|
||
// 删除连接 true -> success / false -> failed
|
||
bool Workflow_Editor::Del_Link(int source_connector_id, int target_connector_id)
|
||
{
|
||
// 遍历边池,删除对应的边
|
||
for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++)
|
||
if ((iterator->source_connector_id == source_connector_id) && (iterator->target_connector_id == target_connector_id))
|
||
{
|
||
this->Del_Link(iterator);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
// 创建工作路由 true -> success / false -> failed
|
||
bool Workflow_Editor::Build_Process_Route(void)
|
||
{
|
||
this->Clear_Process_Route();
|
||
|
||
// 找出所有的头节点
|
||
std::vector<std::shared_ptr<Abs_Node>> Head_List;
|
||
for (auto pNode : this->Node_Pool)
|
||
{
|
||
if (pNode->Get_Type() == Abs_Node::NODE_TYPE_MSG_LINE_INPUT)
|
||
Head_List.push_back(pNode);
|
||
}
|
||
|
||
// 没有可以构建的工作序列
|
||
if (Head_List.size() == 0)
|
||
return false;
|
||
|
||
// 工具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;
|
||
};
|
||
|
||
// 处理所有头节点工作流程
|
||
for (auto pNode : Head_List)
|
||
{
|
||
// 工作序列
|
||
std::vector<std::shared_ptr<Abs_Node>> Process_Sequence_List; // 处理序列
|
||
std::vector<std::shared_ptr<Abs_Node>> pRelated_List; // 关联节点列表
|
||
|
||
// 构建相关节点列表
|
||
auto Lambda_Find_Related_List = [&](auto self, std::shared_ptr<Abs_Node> pTargetNode) -> void
|
||
{
|
||
// 记录自身到关联列表中
|
||
pRelated_List.push_back(pTargetNode);
|
||
|
||
// 查找当前节点的关联节点
|
||
std::vector<decltype(pTargetNode)> Target_Related_Node_List;
|
||
for (auto pConnector : pTargetNode->Get_Connector_List())
|
||
{
|
||
for (auto pRelated_Connector : pConnector->Get_Related_List())
|
||
{
|
||
auto pRelated_Node = Lambda_Find_Owner(pRelated_Connector->Get_ID());
|
||
bool duplicated = false;
|
||
|
||
// 查重并加入子节点列表
|
||
for (auto pNode : Target_Related_Node_List)
|
||
{
|
||
if (pNode == pRelated_Node)
|
||
{
|
||
duplicated = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!duplicated)
|
||
Target_Related_Node_List.push_back(pRelated_Node);
|
||
}
|
||
}
|
||
|
||
// 泛洪检查所有相邻的节点
|
||
for (auto pNode : Target_Related_Node_List)
|
||
{
|
||
bool find = false;
|
||
for (auto pCheckedNode : pRelated_List)
|
||
if (pCheckedNode == pNode)
|
||
{
|
||
find = true;
|
||
break;
|
||
}
|
||
|
||
// 当前关联节点未被记录时,递归顺延泛洪
|
||
if (!find)
|
||
self(self, pNode);
|
||
}
|
||
};
|
||
|
||
// 工具Lambda表达式,检查依赖节点 true -> ALL Dependency Find
|
||
auto Lambda_Check_Dependency = [&](Abs_Node *pTargetNode) -> bool
|
||
{
|
||
// 查找目标节点的依赖节点列表
|
||
std::vector<std::shared_ptr<Abs_Node>> Dependency_NodeList;
|
||
for (auto pConnector : pTargetNode->Get_Connector_List())
|
||
{
|
||
if (pConnector->Get_Type() == Abs_Connector::CONNECTOR_TYPE_INPUT)
|
||
{
|
||
for (auto pPreConnector : pConnector->Get_Related_List())
|
||
{
|
||
auto pPreNode = Lambda_Find_Owner(pPreConnector->Get_ID());
|
||
bool duplicated = false;
|
||
|
||
// 查重并加入依赖关系列表
|
||
for (auto pNode : Dependency_NodeList)
|
||
{
|
||
if (pNode == pPreNode)
|
||
{
|
||
duplicated = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!duplicated)
|
||
Dependency_NodeList.push_back(pPreNode);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 比对依赖的节点和已处理的节点
|
||
bool all_find_flag = true;
|
||
for (auto pDependencyNode : Dependency_NodeList)
|
||
{
|
||
bool find = false;
|
||
for (auto pProcessedNode : Process_Sequence_List)
|
||
{
|
||
if (pDependencyNode == pProcessedNode)
|
||
{
|
||
find = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!find)
|
||
{
|
||
all_find_flag = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return all_find_flag;
|
||
};
|
||
|
||
// 构建处理序列,遍历所有关联节点直到不存在散点,每次都加入已经满足依赖的所有节点
|
||
Lambda_Find_Related_List(Lambda_Find_Related_List, pNode);
|
||
while (pRelated_List.size() > 0)
|
||
{
|
||
for (auto iterator = pRelated_List.begin(); iterator != pRelated_List.end(); iterator++)
|
||
{
|
||
if (Lambda_Check_Dependency(iterator->get()) == true)
|
||
{
|
||
Process_Sequence_List.push_back(*iterator);
|
||
iterator = pRelated_List.erase(iterator) - 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 工作序列中仅孤立节点时不加入工作路由表
|
||
if (Process_Sequence_List.size() > 1)
|
||
this->Process_Route.push_back(Process_Sequence_List);
|
||
}
|
||
|
||
/**
|
||
* @todo
|
||
* 工作路由序列合法性检查
|
||
* 非法 -> return false
|
||
*/
|
||
|
||
return true;
|
||
}
|
||
|
||
// 清除工作路由 true -> success / false -> failed
|
||
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<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;
|
||
} |