Compare commits
5
Commits
Ver1.0
...
f6e70335f9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6e70335f9 | ||
|
|
b86798db10 | ||
|
|
2972630f25 | ||
|
|
0f2f2720fc | ||
|
|
cfb1be0efd |
@@ -145,6 +145,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list));
|
size_t get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 将消息列表按时间戳排序
|
||||||
|
* @param null
|
||||||
|
* @return DLT_Type::DLT_Err 错误类型枚举
|
||||||
|
*/
|
||||||
|
DLT_Type::DLT_Err sort_msg_list(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 导出为CSV
|
* @brief 导出为CSV
|
||||||
* @param file_name_str 目标文件名
|
* @param file_name_str 目标文件名
|
||||||
|
|||||||
@@ -5,14 +5,15 @@
|
|||||||
#include "imgui_impl_win32.h"
|
#include "imgui_impl_win32.h"
|
||||||
#include "imgui_impl_dx11.h"
|
#include "imgui_impl_dx11.h"
|
||||||
|
|
||||||
|
#include "Workflow_Editor.hpp"
|
||||||
|
#include "Type_Descriptions.hpp"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "d3d11.h"
|
#include "d3d11.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "Type_Descriptions.hpp"
|
|
||||||
|
|
||||||
// 主窗体句柄
|
// 主窗体句柄
|
||||||
extern HWND Main_Window_hWnd;
|
extern HWND Main_Window_hWnd;
|
||||||
|
|
||||||
@@ -29,4 +30,7 @@ extern ID3D11RenderTargetView *g_mainRenderTargetView; // D3D11 渲染目标
|
|||||||
extern Input_File_Node *input_dlt_file_list_head;
|
extern Input_File_Node *input_dlt_file_list_head;
|
||||||
extern size_t input_dlt_file_count;
|
extern size_t input_dlt_file_count;
|
||||||
|
|
||||||
|
// 节点编辑器
|
||||||
|
extern class Workflow_Editor Workflow_Editor;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef __WORKFLOW_EDITOR_HPP__
|
||||||
|
#define __WORKFLOW_EDITOR_HPP__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imnodes.h"
|
||||||
|
#include "ID_Generator.hpp"
|
||||||
|
#include "Nodes_And_Connectors.hpp"
|
||||||
|
|
||||||
|
// 节点编辑器类
|
||||||
|
class Workflow_Editor
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
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:
|
||||||
|
// 绘制节点编辑器
|
||||||
|
void Show(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -41,7 +41,7 @@ COMPLIER_PREFIX = \
|
|||||||
C_COMPLIER = $(strip $(COMPLIER_PREFIX))gcc
|
C_COMPLIER = $(strip $(COMPLIER_PREFIX))gcc
|
||||||
|
|
||||||
# C++编译工具
|
# C++编译工具
|
||||||
C++_COMPLIER = $(strip $(COMPLIER_PREFIX))g++
|
CXX_COMPLIER = $(strip $(COMPLIER_PREFIX))g++
|
||||||
|
|
||||||
# Windows 资源文件编译工具
|
# Windows 资源文件编译工具
|
||||||
WIN_RES_COMPLIER = windres
|
WIN_RES_COMPLIER = windres
|
||||||
@@ -194,13 +194,13 @@ $(BUILD_DIR)/$(SUB_DIR_DEBUG): | $(BUILD_DIR)
|
|||||||
# Release 最终可执行文件编译任务
|
# Release 最终可执行文件编译任务
|
||||||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe: $(RELEASE_OBJECTS)
|
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(TARGET_FILE_NAME).exe: $(RELEASE_OBJECTS)
|
||||||
@echo ====== [Release] All File Compiled. Now Linking... ======
|
@echo ====== [Release] All File Compiled. Now Linking... ======
|
||||||
$(C++_COMPLIER) $(RELEASE_OBJECTS) -static -o $@ $(LIB_LINK) $(LDFLAGS)
|
$(CXX_COMPLIER) $(RELEASE_OBJECTS) -static -o $@ $(LIB_LINK) $(LDFLAGS)
|
||||||
@echo ====== [Release] Program Link Finished ======
|
@echo ====== [Release] Program Link Finished ======
|
||||||
|
|
||||||
# Debug 最终可执行文件编译任务
|
# Debug 最终可执行文件编译任务
|
||||||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe: $(DEBUG_OBJECTS)
|
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(TARGET_FILE_NAME).exe: $(DEBUG_OBJECTS)
|
||||||
@echo ====== [Debug] All File Compiled. Now Linking... ======
|
@echo ====== [Debug] All File Compiled. Now Linking... ======
|
||||||
$(C++_COMPLIER) $(DEBUG_OBJECTS) -static -o $@ $(LIB_LINK) $(LDFLAGS)
|
$(CXX_COMPLIER) $(DEBUG_OBJECTS) -static -o $@ $(LIB_LINK) $(LDFLAGS)
|
||||||
@echo ====== [Debug] Program Link Finished ======
|
@echo ====== [Debug] Program Link Finished ======
|
||||||
|
|
||||||
# C Release 目标文件编译
|
# C Release 目标文件编译
|
||||||
@@ -211,7 +211,7 @@ $(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEA
|
|||||||
# C++ Release 目标文件编译
|
# C++ Release 目标文件编译
|
||||||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
||||||
@echo ====== [Release] C++ Source File "$<" Compiling... ======
|
@echo ====== [Release] C++ Source File "$<" Compiling... ======
|
||||||
$(C++_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) -Wa,-a,-ad,-ahlms=$(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(notdir $(<:.cpp=.lst)) $< -o $@
|
$(CXX_COMPLIER) -c $(CXXFLAGS) $(RELEASE_OPT) -Wa,-a,-ad,-ahlms=$(BUILD_DIR)/$(SUB_DIR_RELEASE)/$(notdir $(<:.cpp=.lst)) $< -o $@
|
||||||
|
|
||||||
# Release 资源脚本文件编译
|
# Release 资源脚本文件编译
|
||||||
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
$(BUILD_DIR)/$(SUB_DIR_RELEASE)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_RELEASE)
|
||||||
@@ -226,7 +226,7 @@ $(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.c Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
|||||||
# C++ Debug 目标文件编译
|
# C++ Debug 目标文件编译
|
||||||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.cpp Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
||||||
@echo ====== [Debug] C++ Source File "$<" Compiling... ======
|
@echo ====== [Debug] C++ Source File "$<" Compiling... ======
|
||||||
$(C++_COMPLIER) -c $(CXXFLAGS) $(DEBUG_OPT) -g -Wa,-a,-ad,-ahlms=$(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(notdir $(<:.cpp=.lst)) $< -o $@
|
$(CXX_COMPLIER) -c $(CXXFLAGS) $(DEBUG_OPT) -g -Wa,-a,-ad,-ahlms=$(BUILD_DIR)/$(SUB_DIR_DEBUG)/$(notdir $(<:.cpp=.lst)) $< -o $@
|
||||||
|
|
||||||
# Debug 资源脚本文件编译
|
# Debug 资源脚本文件编译
|
||||||
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
$(BUILD_DIR)/$(SUB_DIR_DEBUG)/%.o: %.rc Makefile | $(BUILD_DIR)/$(SUB_DIR_DEBUG)
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "CSV_Utilities.hpp"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "CSV_Utilities.hpp"
|
||||||
|
|
||||||
DLT_Log File;
|
DLT_Log File;
|
||||||
|
|
||||||
// 命令行处理
|
// 命令行处理
|
||||||
|
|||||||
+92
-6
@@ -285,6 +285,82 @@ size_t DLT_Log::get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list))
|
|||||||
return this->loaded_msg_count;
|
return this->loaded_msg_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLT_Type::DLT_Err DLT_Log::sort_msg_list(void)
|
||||||
|
{
|
||||||
|
// 临时分配的排序用指针数组
|
||||||
|
DLT_Type::DLT_Msg_Node **Node_P_Arr = (DLT_Type::DLT_Msg_Node **)malloc(sizeof(DLT_Type::DLT_Msg_Node *) * this->loaded_msg_count);
|
||||||
|
if (Node_P_Arr == nullptr)
|
||||||
|
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
|
||||||
|
|
||||||
|
// 填充地址数组
|
||||||
|
{
|
||||||
|
DLT_Type::DLT_Msg_Node *p_target_node = this->Msg_List_Head;
|
||||||
|
for (size_t count = 0; count < loaded_msg_count; count++)
|
||||||
|
{
|
||||||
|
Node_P_Arr[count] = p_target_node;
|
||||||
|
p_target_node = p_target_node->p_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// qsort排序
|
||||||
|
qsort(Node_P_Arr,
|
||||||
|
loaded_msg_count,
|
||||||
|
sizeof(DLT_Type::DLT_Msg_Node *),
|
||||||
|
|
||||||
|
// 升序,小时间戳在前
|
||||||
|
[](const void *param1, const void *param2) -> int
|
||||||
|
{
|
||||||
|
DLT_Type::DLT_Msg_Node *Node1 = *(DLT_Type::DLT_Msg_Node **)param1;
|
||||||
|
DLT_Type::DLT_Msg_Node *Node2 = *(DLT_Type::DLT_Msg_Node **)param2;
|
||||||
|
if (Node1->Msg.storage_header.seconds > Node2->Msg.storage_header.seconds)
|
||||||
|
return 1;
|
||||||
|
else if (Node1->Msg.storage_header.seconds == Node2->Msg.storage_header.seconds)
|
||||||
|
{
|
||||||
|
if (Node1->Msg.storage_header.microseconds > Node2->Msg.storage_header.microseconds)
|
||||||
|
return 1;
|
||||||
|
else if (Node1->Msg.storage_header.microseconds == Node2->Msg.storage_header.microseconds)
|
||||||
|
{
|
||||||
|
// 存在0.1ms时间戳
|
||||||
|
if (Node1->Msg.standard_header.htyp.WTMS && Node2->Msg.standard_header.htyp.WTMS)
|
||||||
|
{
|
||||||
|
if (Node1->Msg.standard_header_extra.tmsp > Node2->Msg.standard_header_extra.tmsp)
|
||||||
|
return 1;
|
||||||
|
else if (Node1->Msg.standard_header_extra.tmsp == Node2->Msg.standard_header_extra.tmsp)
|
||||||
|
return 0;
|
||||||
|
else if (Node1->Msg.standard_header_extra.tmsp < Node2->Msg.standard_header_extra.tmsp)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 重新连接消息列表
|
||||||
|
{
|
||||||
|
this->Msg_List_Head = Node_P_Arr[0];
|
||||||
|
this->Msg_List_End = Node_P_Arr[this->loaded_msg_count - 1];
|
||||||
|
this->Msg_List_End->p_next = nullptr;
|
||||||
|
|
||||||
|
DLT_Type::DLT_Msg_Node *p_target = Node_P_Arr[0];
|
||||||
|
for (size_t count = 1; count < this->loaded_msg_count; count++)
|
||||||
|
{
|
||||||
|
p_target->p_next = Node_P_Arr[count];
|
||||||
|
p_target = p_target->p_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 释放空间
|
||||||
|
free(Node_P_Arr);
|
||||||
|
return DLT_Type::DLT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
||||||
{
|
{
|
||||||
FILE *p_file = fopen(file_name_str, "wb");
|
FILE *p_file = fopen(file_name_str, "wb");
|
||||||
@@ -327,13 +403,23 @@ DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
|||||||
/**< Timestamp since system start in 0.1 milliseconds */
|
/**< Timestamp since system start in 0.1 milliseconds */
|
||||||
char time_str[20];
|
char time_str[20];
|
||||||
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
|
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
|
||||||
char *p_sec_end = time_str + strlen(time_str) - 4;
|
if (strlen(time_str) > 4)
|
||||||
|
{
|
||||||
|
char *p_sec_end = time_str + strlen(time_str) - 4;
|
||||||
|
|
||||||
// 输出秒
|
// 输出秒
|
||||||
for (char *p = time_str; p < p_sec_end; p++)
|
for (char *p = time_str; p < p_sec_end; p++)
|
||||||
fputc(*p, p_file);
|
fputc(*p, p_file);
|
||||||
// 输出剩余的时间
|
// 输出剩余的时间
|
||||||
fprintf(p_file, ".%s,", p_sec_end);
|
fprintf(p_file, ".%s,", p_sec_end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(p_file, "0.");
|
||||||
|
for (int count = 4 - strlen(time_str); count > 0; count--)
|
||||||
|
fputc('0', p_file);
|
||||||
|
fprintf(p_file, "%s,", time_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf(p_file, "N/A,");
|
fprintf(p_file, "N/A,");
|
||||||
|
|||||||
@@ -14,4 +14,7 @@ ID3D11RenderTargetView *g_mainRenderTargetView = nullptr; // D3D11 渲染目标
|
|||||||
|
|
||||||
// 文件输入相关
|
// 文件输入相关
|
||||||
Input_File_Node *input_dlt_file_list_head;
|
Input_File_Node *input_dlt_file_list_head;
|
||||||
size_t input_dlt_file_count;
|
size_t input_dlt_file_count;
|
||||||
|
|
||||||
|
// 节点编辑器
|
||||||
|
class Workflow_Editor Workflow_Editor;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
};
|
||||||
+47
-7
@@ -36,24 +36,62 @@ void UI_Layout()
|
|||||||
// 设置窗体相关属性,不允许停靠
|
// 设置窗体相关属性,不允许停靠
|
||||||
window_flags |= ImGuiWindowFlags_NoDocking;
|
window_flags |= ImGuiWindowFlags_NoDocking;
|
||||||
|
|
||||||
|
// 临时设置一下窗体大小,动态扩张窗体
|
||||||
|
{
|
||||||
|
static size_t Width = MAIN_FRAME_SIZE_WIDTH_MIN;
|
||||||
|
static size_t Height = MAIN_FRAME_SIZE_HEIGHT_MIN;
|
||||||
|
if (!(Width >= 1400 && Height >= 700))
|
||||||
|
{
|
||||||
|
SetWindowPos(
|
||||||
|
Main_Window_hWnd,
|
||||||
|
NULL,
|
||||||
|
(GetSystemMetrics(SM_CXSCREEN) - (Width)) / 2,
|
||||||
|
(GetSystemMetrics(SM_CYSCREEN) - (Height)) / 2,
|
||||||
|
Width,
|
||||||
|
Height,
|
||||||
|
SWP_NOZORDER);
|
||||||
|
|
||||||
|
if (Height < 700)
|
||||||
|
Height += 5;
|
||||||
|
if (Width < 1400)
|
||||||
|
Width += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Begin("Main Panel", NULL, window_flags); // 创建主面板
|
ImGui::Begin("Main Panel", NULL, window_flags); // 创建主面板
|
||||||
ImGui::PopStyleVar(2); // 退出绘制风格栈中的设置项
|
ImGui::PopStyleVar(2); // 退出绘制风格栈中的设置项
|
||||||
{
|
{
|
||||||
const ImGuiStyle &style = ImGui::GetStyle();
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));
|
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));
|
||||||
|
|
||||||
// 拖拽输入区域
|
// 左半部分
|
||||||
Widgets::Drag_Input_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().x / 2 > MAIN_FRAME_SIZE_WIDTH_MIN / 2 ? MAIN_FRAME_SIZE_WIDTH_MIN / 2 : ImGui::GetContentRegionAvail().x / 2));
|
ImGui::BeginChild("Left Part", ImVec2(MAIN_FRAME_SIZE_WIDTH_MIN, ImGui::GetContentRegionAvail().y));
|
||||||
|
{
|
||||||
|
|
||||||
// 文件列表组件
|
// 拖拽输入区域
|
||||||
Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));
|
Widgets::Drag_Input_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().x / 2 > MAIN_FRAME_SIZE_WIDTH_MIN * main_scale / 2 ? MAIN_FRAME_SIZE_WIDTH_MIN * main_scale / 2 : ImGui::GetContentRegionAvail().x / 2));
|
||||||
|
|
||||||
// 导出文件
|
// 文件列表组件
|
||||||
Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale));
|
Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));
|
||||||
|
|
||||||
|
// 导出文件
|
||||||
|
Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale));
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
// 右半部分
|
||||||
|
ImGui::BeginChild("Right Part", ImVec2(0, 0));
|
||||||
|
{
|
||||||
|
// 工作流节点编辑器
|
||||||
|
Workflow_Editor.Show();
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
// ImGui::ShowDemoWindow(nullptr);
|
ImGui::ShowDemoWindow(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widgets::Drag_Input_Area(const ImVec2 &size)
|
void Widgets::Drag_Input_Area(const ImVec2 &size)
|
||||||
@@ -395,6 +433,8 @@ void Widgets::Control_Panel(const ImVec2 &size)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// 排序后导出
|
||||||
|
Log.sort_msg_list();
|
||||||
err = Log.export_to_csv(export_file_path_str);
|
err = Log.export_to_csv(export_file_path_str);
|
||||||
|
|
||||||
if (err == DLT_Type::DLT_ERROR_NONE)
|
if (err == DLT_Type::DLT_ERROR_NONE)
|
||||||
|
|||||||
@@ -0,0 +1,217 @@
|
|||||||
|
#include "Workflow_Editor.hpp"
|
||||||
|
#include "imgui_internal.h"
|
||||||
|
|
||||||
|
// 新增节点
|
||||||
|
bool Workflow_Editor::Add_Node(Node_Type_Enum type, ImVec2 initial_position)
|
||||||
|
{
|
||||||
|
// 新节点
|
||||||
|
std::shared_ptr<Abs_Node> p_New_Node;
|
||||||
|
|
||||||
|
// 记录节点
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 记录到散点池
|
||||||
|
this->Separate_Node_List.push_back(p_New_Node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绘制节点编辑器
|
||||||
|
void Workflow_Editor::Show(void)
|
||||||
|
{
|
||||||
|
// 浅色主题节点编辑器窗体
|
||||||
|
ImNodes::StyleColorsLight();
|
||||||
|
ImNodes::BeginNodeEditor();
|
||||||
|
{
|
||||||
|
// 显示所有节点
|
||||||
|
for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++)
|
||||||
|
{
|
||||||
|
auto Connector_List = (*iterator)->Get_Connector_List();
|
||||||
|
if ((*iterator)->Get_CloseFlag() == true)
|
||||||
|
{
|
||||||
|
// 删除列表中所有与该节点接口相关的边并从接口池中删除
|
||||||
|
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 (open_popup)
|
||||||
|
{
|
||||||
|
ImGui::OpenPopup("RightClick_Popup");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("RightClick_Popup"))
|
||||||
|
{
|
||||||
|
ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup();
|
||||||
|
// 节点添加菜单
|
||||||
|
if (ImGui::BeginMenu(u8"创建节点"))
|
||||||
|
{
|
||||||
|
if (ImGui::MenuItem(u8"DLT信息输入节点"))
|
||||||
|
this->Add_Node(NODE_TYPE_MSG_LINE_INPUT, click_pos);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 处理连线
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (find)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判定查找结果
|
||||||
|
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 调整工作路由层级
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user