Compare commits
2 Commits
2972630f25
...
f6e70335f9
| Author | SHA1 | Date | |
|---|---|---|---|
| f6e70335f9 | |||
| b86798db10 |
@ -5,15 +5,15 @@
|
||||
#include "imgui_impl_win32.h"
|
||||
#include "imgui_impl_dx11.h"
|
||||
|
||||
#include "Workflow_Editor.hpp"
|
||||
#include "Type_Descriptions.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "windows.h"
|
||||
#include "d3d11.h"
|
||||
}
|
||||
|
||||
#include "Type_Descriptions.hpp"
|
||||
#include "Workflow-Editor.hpp"
|
||||
|
||||
// 主窗体句柄
|
||||
extern HWND Main_Window_hWnd;
|
||||
|
||||
@ -31,6 +31,6 @@ extern Input_File_Node *input_dlt_file_list_head;
|
||||
extern size_t input_dlt_file_count;
|
||||
|
||||
// 节点编辑器
|
||||
extern Workflow_Editor_Class Workflow_Editor;
|
||||
extern class Workflow_Editor Workflow_Editor;
|
||||
|
||||
#endif
|
||||
25
Inc/ID_Generator.hpp
Normal file
25
Inc/ID_Generator.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef __ID_GENERATOR__
|
||||
#define __ID_GENERATOR__
|
||||
|
||||
#include <vector>
|
||||
|
||||
// 唯一ID生成器
|
||||
class Independent_ID_Generator
|
||||
{
|
||||
protected:
|
||||
// 连续ID串
|
||||
typedef struct
|
||||
{
|
||||
int begin;
|
||||
int end;
|
||||
} Continuous_ID_Section;
|
||||
std::vector<Continuous_ID_Section> continuous_id_list;
|
||||
|
||||
public:
|
||||
// 获取ID
|
||||
int Request_ID(void);
|
||||
// 释放ID true-> success / false -> fail
|
||||
bool Release_ID(const int ID);
|
||||
};
|
||||
|
||||
#endif
|
||||
214
Inc/Nodes_And_Connectors.hpp
Normal file
214
Inc/Nodes_And_Connectors.hpp
Normal file
@ -0,0 +1,214 @@
|
||||
#ifndef __NODES_AND_CONNECTORS__
|
||||
#define __NODES_AND_CONNECTORS__
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "imgui.h"
|
||||
#include "imnodes.h"
|
||||
#include "ID_Generator.hpp"
|
||||
|
||||
// =====================================接口抽象======================================================
|
||||
|
||||
class Abs_Connector // 抽象接口类
|
||||
{
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
CONNECTOR_TYPE_UNKNOWN, // 未知连接点类型
|
||||
CONNECTOR_TYPE_OUTPUT, // 输出
|
||||
CONNECTOR_TYPE_INPUT, // 输入
|
||||
} Connector_Type_Enum; // 接口类型枚举
|
||||
|
||||
// ID 分配器
|
||||
Independent_ID_Generator *ID_Generator;
|
||||
|
||||
int id; // ID
|
||||
Connector_Type_Enum type; // 类型标识
|
||||
const char *socket_str; // 套接字字符串
|
||||
|
||||
Abs_Connector *provider; // 提供者
|
||||
std::vector<Abs_Connector *> receiver_list; // 接收方
|
||||
void *product; // 产物
|
||||
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
Abs_Connector() = delete;
|
||||
|
||||
// 必要构造
|
||||
Abs_Connector(Independent_ID_Generator *ID_Generator, Connector_Type_Enum type, const char *socket_str);
|
||||
|
||||
// 析构
|
||||
~Abs_Connector();
|
||||
|
||||
// 连接到目标连接点
|
||||
virtual bool Connect_To(Abs_Connector *target);
|
||||
|
||||
// 断开连接
|
||||
virtual void Disconnect(void);
|
||||
|
||||
// 注册产物
|
||||
virtual bool Register_Product(void *product, size_t size);
|
||||
|
||||
// 获取上级节点
|
||||
virtual Abs_Connector *Get_Provider(void);
|
||||
|
||||
// 获取产物
|
||||
virtual void *Get_Product(void);
|
||||
|
||||
// 获取ID
|
||||
virtual int Get_ID(void);
|
||||
|
||||
// 绘制连接点
|
||||
virtual void Show(void) = 0;
|
||||
};
|
||||
|
||||
// =====================================节点抽象======================================================
|
||||
|
||||
class Abs_Node // 抽象节点类
|
||||
{
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
NODE_TYPE_UNKNOWN, // 未知节点类型
|
||||
NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点
|
||||
NODE_TYPE_CSV_EXPORTER, // CSV输出节点
|
||||
} Node_Type_Enum; // 节点类型枚举
|
||||
|
||||
// ID 分配器
|
||||
Independent_ID_Generator *Node_ID_Generator; // 节点ID生成器
|
||||
Independent_ID_Generator *Connector_ID_Generator; // 连接点ID生成器
|
||||
|
||||
int id; // ID
|
||||
Node_Type_Enum type; // 类型
|
||||
ImVec2 initial_position; // 初始位置
|
||||
|
||||
bool close_flag; // 关闭标志位
|
||||
|
||||
// 接口列表
|
||||
std::vector<std::shared_ptr<Abs_Connector>> Connector_List;
|
||||
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
Abs_Node() = delete;
|
||||
|
||||
// 必要构造
|
||||
Abs_Node(Independent_ID_Generator *Node_ID_Generator,
|
||||
Independent_ID_Generator *Connector_ID_Generator,
|
||||
Node_Type_Enum type,
|
||||
ImVec2 initial_position = ImVec2(0, 0));
|
||||
|
||||
// 析构
|
||||
~Abs_Node();
|
||||
|
||||
// 绘制节点
|
||||
virtual void Show(void) = 0;
|
||||
|
||||
// 执行处理流程
|
||||
virtual bool Execute_Process(void) = 0;
|
||||
|
||||
// 获取关闭信号
|
||||
virtual bool Get_CloseFlag(void);
|
||||
|
||||
// 获取接口列表
|
||||
std::vector<std::shared_ptr<Abs_Connector>> &Get_Connector_List(void);
|
||||
};
|
||||
|
||||
// ====================================接口类声明================================================
|
||||
|
||||
// DLT信息输出接口
|
||||
class MSG_OutPut_Connector : public Abs_Connector
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
MSG_OutPut_Connector() = delete;
|
||||
|
||||
// 必要构造
|
||||
explicit MSG_OutPut_Connector(Independent_ID_Generator *ID_Generator);
|
||||
|
||||
// 绘制接口
|
||||
virtual void Show(void);
|
||||
};
|
||||
|
||||
// DLT信息输入接口
|
||||
class MSG_InPut_Connector : public Abs_Connector
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
MSG_InPut_Connector() = delete;
|
||||
|
||||
// 必要构造
|
||||
explicit MSG_InPut_Connector(Independent_ID_Generator *ID_Generator);
|
||||
|
||||
// 绘制接口
|
||||
virtual void Show(void);
|
||||
};
|
||||
|
||||
// CSV 列输入接口
|
||||
class CSV_Column_Input_Connector : public Abs_Connector
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
CSV_Column_Input_Connector() = delete;
|
||||
|
||||
// 必要构造
|
||||
explicit CSV_Column_Input_Connector(Independent_ID_Generator *ID_Generator);
|
||||
|
||||
// 绘制接口
|
||||
virtual void Show(void);
|
||||
};
|
||||
|
||||
// CSV 列输出接口
|
||||
class CSV_Column_Output_Connector : public Abs_Connector
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
CSV_Column_Output_Connector() = delete;
|
||||
|
||||
// 必要构造
|
||||
explicit CSV_Column_Output_Connector(Independent_ID_Generator *ID_Generator);
|
||||
|
||||
// 绘制接口
|
||||
virtual void Show(void);
|
||||
};
|
||||
|
||||
// ====================================节点类声明================================================
|
||||
|
||||
// 接口测试节点
|
||||
class Connector_Test_Node : public Abs_Node
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
Connector_Test_Node() = delete;
|
||||
|
||||
// 必要构造
|
||||
Connector_Test_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);
|
||||
};
|
||||
|
||||
// DLT信息输入类,起始点
|
||||
class MSG_Input_Node : public Abs_Node
|
||||
{
|
||||
public:
|
||||
// 显式禁用默认构造
|
||||
MSG_Input_Node() = delete;
|
||||
|
||||
// 必要构造
|
||||
MSG_Input_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
|
||||
@ -1,89 +1,58 @@
|
||||
#ifndef __WORKFLOW_EDITOR_HPP__
|
||||
#define __WORKFLOW_EDITOR_HPP__
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "stdint.h"
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
||||
// // 并行工作链
|
||||
// class Parallel_Working_List
|
||||
// {
|
||||
// private:
|
||||
// // 节点计数
|
||||
// size_t node_count;
|
||||
|
||||
// // 内部迭代器
|
||||
// class iterator
|
||||
// {
|
||||
// };
|
||||
|
||||
// public:
|
||||
// iterator begin() { return iterator(arr); }
|
||||
// iterator end() { return iterator(arr + SIZE); }
|
||||
// };
|
||||
|
||||
// 节点类型枚举
|
||||
typedef enum
|
||||
{
|
||||
NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点
|
||||
NODE_TYPE_CSV_EXPORTER, // CSV输出节点
|
||||
} NodeType;
|
||||
|
||||
// 节点基类
|
||||
class Node_Class
|
||||
{
|
||||
protected:
|
||||
int id; // 节点ID
|
||||
bool initial_state; // 初始状态
|
||||
ImVec2 initial_position; // 初始位置
|
||||
|
||||
public:
|
||||
// 初始化列表构造
|
||||
explicit Node_Class(int id, ImVec2 initial_position = ImVec2(0, 0)) : id(id), initial_state(true), initial_position(initial_position) {}
|
||||
int getID() { return this->id; }
|
||||
|
||||
/**
|
||||
* 显示节点并获取状态(子类必须实现)
|
||||
* @param null
|
||||
* @return 0 -> normal : 1-> close
|
||||
*/
|
||||
virtual bool show_and_get_state(void) = 0;
|
||||
|
||||
virtual ~Node_Class() = default; // 抽象基类必须有虚析构函数
|
||||
};
|
||||
|
||||
// 消息输出节点
|
||||
class MsgLine_Input_Node_Class : public Node_Class
|
||||
{
|
||||
public:
|
||||
explicit MsgLine_Input_Node_Class(int id, ImVec2 initial_position = ImVec2(0, 0)) : Node_Class(id, initial_position) {};
|
||||
bool show_and_get_state(void) override;
|
||||
};
|
||||
#include <memory>
|
||||
#include "imgui.h"
|
||||
#include "imnodes.h"
|
||||
#include "ID_Generator.hpp"
|
||||
#include "Nodes_And_Connectors.hpp"
|
||||
|
||||
// 节点编辑器类
|
||||
class Workflow_Editor_Class
|
||||
class Workflow_Editor
|
||||
{
|
||||
protected:
|
||||
// 节点列表
|
||||
std::vector<Node_Class *> Node_List;
|
||||
typedef enum
|
||||
{
|
||||
NODE_TYPE_UNKNOWN, // 未知节点类型
|
||||
NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点
|
||||
NODE_TYPE_CSV_EXPORTER, // CSV输出节点
|
||||
} Node_Type_Enum; // 节点类型枚举
|
||||
|
||||
// ID 分配器
|
||||
Independent_ID_Generator Connector_ID_Generator; // 连接点ID生成器
|
||||
Independent_ID_Generator Node_ID_Generator; // 节点ID生成器
|
||||
Independent_ID_Generator Edge_ID_Generator; // 边ID生成器
|
||||
|
||||
// 边定义
|
||||
typedef struct
|
||||
{
|
||||
int id = -1; // 边ID
|
||||
int source_connector_id = -1; // 源连接点
|
||||
int target_connector_id = -1; // 目标连接点
|
||||
} Edge;
|
||||
|
||||
// 数据池
|
||||
std::vector<std::shared_ptr<Abs_Connector>> Connector_Pool; // 连接点池
|
||||
std::vector<std::shared_ptr<Abs_Node>> Node_Pool; // 节点池
|
||||
std::vector<Edge> Edge_Pool; // 边池
|
||||
|
||||
/**
|
||||
* 顶层索引为启示工作流节点(N个元素即N个处理流程)
|
||||
* 次级索引为工作流分层
|
||||
* 三级索引为平级工作流节点
|
||||
* 不参与工作流节点仅存于散点列表
|
||||
*/
|
||||
std::vector<std::vector<std::vector<std::shared_ptr<Abs_Node>>>> Process_Route; // 工作层级路由
|
||||
std::vector<std::shared_ptr<Abs_Node>> Separate_Node_List; // 散点列表
|
||||
|
||||
// =====================================函数声明=================================================
|
||||
// 新增节点 true -> success / false -> failed
|
||||
bool Add_Node(Node_Type_Enum type, ImVec2 initial_position = ImVec2(0, 0));
|
||||
|
||||
public:
|
||||
// 构造函数
|
||||
Workflow_Editor_Class();
|
||||
|
||||
// 析构函数
|
||||
~Workflow_Editor_Class();
|
||||
|
||||
// 显示工作流节点编辑器
|
||||
// 绘制节点编辑器
|
||||
void Show(void);
|
||||
|
||||
// 新增节点
|
||||
void Add_Node(NodeType type, ImVec2 initial_position = ImVec2(0, 0));
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -4,9 +4,10 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "windows.h"
|
||||
#include "CSV_Utilities.hpp"
|
||||
}
|
||||
|
||||
#include "CSV_Utilities.hpp"
|
||||
|
||||
DLT_Log File;
|
||||
|
||||
// 命令行处理
|
||||
|
||||
@ -17,4 +17,4 @@ Input_File_Node *input_dlt_file_list_head;
|
||||
size_t input_dlt_file_count;
|
||||
|
||||
// 节点编辑器
|
||||
Workflow_Editor_Class Workflow_Editor;
|
||||
class Workflow_Editor Workflow_Editor;
|
||||
98
Src/ID_Generator.cpp
Normal file
98
Src/ID_Generator.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "ID_Generator.hpp"
|
||||
|
||||
// 请求ID
|
||||
int Independent_ID_Generator::Request_ID()
|
||||
{
|
||||
// 没有元素时
|
||||
if (this->continuous_id_list.size() == 0)
|
||||
{
|
||||
this->continuous_id_list.push_back({0, 0});
|
||||
|
||||
// 判定分配情况
|
||||
if (this->continuous_id_list.size() == 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 第一段未从最小 ID 开启
|
||||
auto first_iterator = this->continuous_id_list.begin();
|
||||
if (first_iterator->begin != 0)
|
||||
{
|
||||
if (first_iterator->begin == 1)
|
||||
first_iterator->begin--;
|
||||
else
|
||||
{
|
||||
// 划分新段
|
||||
size_t pre_size = this->continuous_id_list.size();
|
||||
first_iterator = this->continuous_id_list.insert(first_iterator, {0, 0});
|
||||
if (!(this->continuous_id_list.size() > pre_size))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 仅第一段时
|
||||
if (this->continuous_id_list.size() == 1)
|
||||
{
|
||||
first_iterator->end++;
|
||||
return first_iterator->end;
|
||||
}
|
||||
|
||||
// 有两段及以上时,判断是否出现合并
|
||||
auto second_iterator = first_iterator + 1;
|
||||
if (first_iterator->end + 2 == second_iterator->begin)
|
||||
{
|
||||
int target_id = first_iterator->end + 1;
|
||||
first_iterator->end = second_iterator->end;
|
||||
this->continuous_id_list.erase(second_iterator);
|
||||
return target_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
first_iterator->end++;
|
||||
return first_iterator->end;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 释放ID true-> success / false -> fail
|
||||
bool Independent_ID_Generator::Release_ID(const int ID)
|
||||
{
|
||||
// 遍历查找所属片
|
||||
for (auto iterator = this->continuous_id_list.begin(); iterator != this->continuous_id_list.end(); iterator++)
|
||||
{
|
||||
// 找到对应的ID所属片
|
||||
if (ID >= iterator->begin && ID <= iterator->end)
|
||||
{
|
||||
// 散点删除
|
||||
if (iterator->begin == iterator->end)
|
||||
this->continuous_id_list.erase(iterator);
|
||||
else if (ID == iterator->begin) // 前端点
|
||||
iterator->begin++;
|
||||
else if (ID == iterator->end) // 后端点
|
||||
iterator->end--;
|
||||
else // 中间段
|
||||
{
|
||||
// 插入后返回新的迭代器
|
||||
size_t pre_size = this->continuous_id_list.size();
|
||||
iterator = this->continuous_id_list.insert(iterator, {iterator->begin, ID - 1});
|
||||
|
||||
// 判定分配是否成功
|
||||
if (!(this->continuous_id_list.size() > pre_size))
|
||||
return false;
|
||||
|
||||
// 记录ID
|
||||
iterator++;
|
||||
iterator->begin = ID + 1;
|
||||
}
|
||||
|
||||
// 完成并退出
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有找到所属片
|
||||
return false;
|
||||
}
|
||||
378
Src/Nodes_And_Connectors.cpp
Normal file
378
Src/Nodes_And_Connectors.cpp
Normal file
@ -0,0 +1,378 @@
|
||||
#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<std::shared_ptr<Abs_Connector>> &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<MSG_OutPut_Connector>(Connector_ID_Generator));
|
||||
this->Connector_List.push_back(std::make_shared<MSG_InPut_Connector>(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;
|
||||
};
|
||||
@ -1,171 +1,130 @@
|
||||
#include "Workflow-Editor.hpp"
|
||||
#include "imgui.h"
|
||||
#include "Workflow_Editor.hpp"
|
||||
#include "imgui_internal.h"
|
||||
#include "imnodes.h"
|
||||
#include <algorithm>
|
||||
|
||||
// 构造函数
|
||||
Workflow_Editor_Class::Workflow_Editor_Class() {}
|
||||
|
||||
// 析构函数
|
||||
Workflow_Editor_Class::~Workflow_Editor_Class()
|
||||
// 新增节点
|
||||
bool Workflow_Editor::Add_Node(Node_Type_Enum type, ImVec2 initial_position)
|
||||
{
|
||||
// 释放资源
|
||||
for (auto &pNode : this->Node_List)
|
||||
delete pNode;
|
||||
}
|
||||
// 新节点
|
||||
std::shared_ptr<Abs_Node> p_New_Node;
|
||||
|
||||
// 客制化圆形带X按钮
|
||||
bool CircleButtonWithX(const char *id, float radius)
|
||||
// 记录节点
|
||||
switch (type)
|
||||
{
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
case 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;
|
||||
|
||||
// // 记录到节点池和接口池
|
||||
// this->Node_Pool.push_back(p_New_Node);
|
||||
// for (auto p_Connector : p_New_Node->Get_Connector_List())
|
||||
// this->Connector_Pool.push_back(p_Connector);
|
||||
|
||||
// // 编辑工作路由
|
||||
// {
|
||||
// // 起始层级只有起始节点
|
||||
// std::vector<std::shared_ptr<Abs_Node>> Begin_Layer;
|
||||
// Begin_Layer.push_back(p_New_Node);
|
||||
|
||||
// // 层级列表仅有起始层级
|
||||
// std::vector<std::vector<std::shared_ptr<Abs_Node>>> Layer_List;
|
||||
// Layer_List.push_back(Begin_Layer);
|
||||
|
||||
// // 插入工作路由表
|
||||
// this->Process_Route.push_back(Layer_List);
|
||||
// }
|
||||
// return true;
|
||||
|
||||
case NODE_TYPE_CSV_EXPORTER: // CSV输出器
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建ID
|
||||
ImGuiID button_id = window->GetID(id);
|
||||
if (p_New_Node.get() != nullptr)
|
||||
{
|
||||
// 将新增的节点及其接口记录到对应的池
|
||||
this->Node_Pool.push_back(p_New_Node);
|
||||
for (auto p_Connector : p_New_Node->Get_Connector_List())
|
||||
this->Connector_Pool.push_back(p_Connector);
|
||||
|
||||
// 计算按钮位置和大小
|
||||
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))
|
||||
// 记录到散点池
|
||||
this->Separate_Node_List.push_back(p_New_Node);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// 消息行输入节点绘制函数
|
||||
bool MsgLine_Input_Node_Class::show_and_get_state()
|
||||
// 绘制节点编辑器
|
||||
void Workflow_Editor::Show(void)
|
||||
{
|
||||
// 节点宽度
|
||||
const float node_width = 200.0f;
|
||||
bool delete_flag = false;
|
||||
|
||||
// 初始化位置设定
|
||||
if (this->initial_state)
|
||||
{
|
||||
ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position);
|
||||
this->initial_state = false;
|
||||
}
|
||||
|
||||
// 绘制节点
|
||||
ImNodes::BeginNode(this->id);
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));
|
||||
// 标题部分
|
||||
ImNodes::BeginNodeTitleBar();
|
||||
{
|
||||
ImGui::TextUnformatted(u8"DLT-信息输入节点");
|
||||
ImGui::SameLine();
|
||||
ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize(u8"DLT-信息输入节点").x - ImGui::GetTextLineHeight(), 0.0f));
|
||||
ImGui::SameLine();
|
||||
// 绘制关闭按钮
|
||||
if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
|
||||
delete_flag = true;
|
||||
}
|
||||
ImNodes::EndNodeTitleBar();
|
||||
|
||||
// // 正文部分
|
||||
// ImGui::Text(u8"DLT消息输入流\n每次输出一条消息");
|
||||
// ImGui::Text(u8"(节点ID : %d)", this->id);
|
||||
|
||||
// 链接点
|
||||
ImNodes::BeginOutputAttribute(0, 1);
|
||||
// const float label_width = ImGui::CalcTextSize(u8"DLT消息行->").x;
|
||||
// ImGui::Indent(label_width);
|
||||
ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize("(?) DLT MSG ->").x, 0.0f));
|
||||
ImGui::SameLine();
|
||||
|
||||
// Help Mark
|
||||
{
|
||||
ImGui::TextDisabled("(?) ");
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
ImGui::TextUnformatted(u8"每个处理流程开始时,输出一条DLT消息;\n每个此类节点输出的消息均会独立遍历所有输入文件;");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::TextUnformatted("DLT MSG ->");
|
||||
ImNodes::EndOutputAttribute();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImNodes::EndNode();
|
||||
|
||||
// 返回节点状态
|
||||
return delete_flag;
|
||||
}
|
||||
|
||||
// 显示工作流节点编辑器
|
||||
void Workflow_Editor_Class::Show(void)
|
||||
{
|
||||
// 浅色主题
|
||||
// 浅色主题节点编辑器窗体
|
||||
ImNodes::StyleColorsLight();
|
||||
ImNodes::BeginNodeEditor();
|
||||
ImGui::PopStyleVar();
|
||||
{
|
||||
|
||||
// 显示所有节点
|
||||
for (auto iterator = this->Node_List.begin(); iterator != this->Node_List.end(); iterator++)
|
||||
for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++)
|
||||
{
|
||||
if ((*iterator)->show_and_get_state())
|
||||
auto Connector_List = (*iterator)->Get_Connector_List();
|
||||
if ((*iterator)->Get_CloseFlag() == true)
|
||||
{
|
||||
delete *iterator;
|
||||
|
||||
// 迭代器删除后会返回下一个位置的迭代器
|
||||
iterator = this->Node_List.erase(iterator);
|
||||
// 删除列表中所有与该节点接口相关的边并从接口池中删除
|
||||
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);
|
||||
iterator--;
|
||||
}
|
||||
}
|
||||
|
||||
// 从接口池中移除
|
||||
for (auto iterator = this->Connector_Pool.begin(); iterator != this->Connector_Pool.end(); iterator++)
|
||||
{
|
||||
if (*iterator == pConnector)
|
||||
{
|
||||
// 注销节点记录
|
||||
iterator = this->Connector_Pool.erase(iterator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo 从工作路由中删除该节点并调整工作路由层级顺序
|
||||
* @todo 可能不需要对外暴露接口池
|
||||
*/
|
||||
|
||||
// 从节点池中删除该节点,迭代器删除后会返回下一个位置的迭代器
|
||||
iterator = this->Node_Pool.erase(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 (!ImGui::IsAnyItemHovered() && open_popup)
|
||||
if (open_popup)
|
||||
{
|
||||
ImGui::OpenPopup("RightClick_Popup");
|
||||
}
|
||||
@ -174,77 +133,85 @@ void Workflow_Editor_Class::Show(void)
|
||||
{
|
||||
ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup();
|
||||
// 节点添加菜单
|
||||
if (ImGui::BeginMenu("Add Nodes"))
|
||||
if (ImGui::BeginMenu(u8"创建节点"))
|
||||
{
|
||||
if (ImGui::MenuItem("Msg input node."))
|
||||
if (ImGui::MenuItem(u8"DLT信息输入节点"))
|
||||
this->Add_Node(NODE_TYPE_MSG_LINE_INPUT, click_pos);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
||||
{
|
||||
// ImNodes::BeginNode(1);
|
||||
// ImNodes::BeginNodeTitleBar();
|
||||
// 显示所有的连线
|
||||
for (auto Edge : this->Edge_Pool)
|
||||
ImNodes::Link(Edge.id, Edge.source_connector_id, Edge.target_connector_id);
|
||||
|
||||
// // ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 10.0f); // 绘制风格栈压入窗口圆角为0
|
||||
// // ImGui::Button("X");
|
||||
// // ImGui::PopStyleVar();
|
||||
// if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
|
||||
// {
|
||||
// };
|
||||
|
||||
// ImGui::SameLine();
|
||||
// ImGui::TextUnformatted("Output Node");
|
||||
|
||||
// ImNodes::EndNodeTitleBar();
|
||||
|
||||
// ImGui::Text("Test Format %%d :%d", 123);
|
||||
|
||||
// ImGui::Button("Click");
|
||||
|
||||
// ImGui::SameLine();
|
||||
// static bool check = false;
|
||||
// ImGui::Checkbox("", &check);
|
||||
|
||||
// ImNodes::EndNode();
|
||||
}
|
||||
}
|
||||
// 缩略图
|
||||
ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_TopRight);
|
||||
}
|
||||
ImNodes::EndNodeEditor();
|
||||
|
||||
// 处理连线
|
||||
{
|
||||
int source_id = -1, target_id = -1;
|
||||
if (ImNodes::IsLinkCreated(&source_id, &target_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_id)
|
||||
p_source_connector = pConnector;
|
||||
if (pConnector->Get_ID() == target_id)
|
||||
p_target_connector = pConnector;
|
||||
if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr))
|
||||
{
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加指定类型节点
|
||||
void Workflow_Editor_Class::Add_Node(NodeType type, ImVec2 initial_position)
|
||||
{
|
||||
// 获取可用ID
|
||||
auto get_id = [&]() -> int
|
||||
{
|
||||
int target_id = 0;
|
||||
for (auto &pNode : this->Node_List)
|
||||
if (target_id == pNode->getID())
|
||||
target_id++;
|
||||
else
|
||||
break;
|
||||
return target_id;
|
||||
};
|
||||
|
||||
// 记录节点
|
||||
switch (type)
|
||||
{
|
||||
case NODE_TYPE_MSG_LINE_INPUT: // 消息行输入
|
||||
this->Node_List.push_back(new MsgLine_Input_Node_Class(get_id(), initial_position));
|
||||
break;
|
||||
case NODE_TYPE_CSV_EXPORTER: // CSV输出器
|
||||
default:
|
||||
if (find)
|
||||
break;
|
||||
}
|
||||
|
||||
// 重新排序确保后续ID分配正常
|
||||
std::sort(this->Node_List.begin(),
|
||||
this->Node_List.end(),
|
||||
[](Node_Class *a, Node_Class *b) -> bool
|
||||
{ return a->getID() < b->getID(); });
|
||||
// 判定查找结果
|
||||
if (find)
|
||||
{
|
||||
// 输入类型节点只允许一个父接口,输出类型节点可以有多个子接口
|
||||
if (p_target_connector->Get_Provider() != nullptr)
|
||||
{
|
||||
int origin_source_id = p_target_connector->Get_Provider()->Get_ID();
|
||||
for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++)
|
||||
{
|
||||
if (iterator->source_connector_id == origin_source_id && iterator->target_connector_id == target_id)
|
||||
{
|
||||
this->Edge_ID_Generator.Release_ID(iterator->id);
|
||||
this->Edge_Pool.erase(iterator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试连接
|
||||
if (p_source_connector->Connect_To(p_target_connector.get()) == true)
|
||||
{
|
||||
// 记录到边池
|
||||
this->Edge_Pool.push_back({this->Edge_ID_Generator.Request_ID(), source_id, target_id});
|
||||
|
||||
/**
|
||||
* @todo 调整工作路由层级
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user