3 Commits
8 changed files with 498 additions and 19 deletions
+7
View File
@@ -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 目标文件名
+4
View File
@@ -12,6 +12,7 @@ extern "C"
} }
#include "Type_Descriptions.hpp" #include "Type_Descriptions.hpp"
#include "Workflow-Editor.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 Workflow_Editor_Class Workflow_Editor;
#endif #endif
+89
View File
@@ -0,0 +1,89 @@
#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;
};
// 节点编辑器类
class Workflow_Editor_Class
{
protected:
// 节点列表
std::vector<Node_Class *> Node_List;
public:
// 构造函数
Workflow_Editor_Class();
// 析构函数
~Workflow_Editor_Class();
// 显示工作流节点编辑器
void Show(void);
// 新增节点
void Add_Node(NodeType type, ImVec2 initial_position = ImVec2(0, 0));
};
#endif
+5 -5
View File
@@ -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)
+86
View File
@@ -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,6 +403,8 @@ 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);
if (strlen(time_str) > 4)
{
char *p_sec_end = time_str + strlen(time_str) - 4; char *p_sec_end = time_str + strlen(time_str) - 4;
// 输出秒 // 输出秒
@@ -335,6 +413,14 @@ DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
// 输出剩余的时间 // 输出剩余的时间
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,");
+3
View File
@@ -15,3 +15,6 @@ 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;
// 节点编辑器
Workflow_Editor_Class Workflow_Editor;
+42 -2
View File
@@ -36,14 +36,40 @@ 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));
// 左半部分
ImGui::BeginChild("Left Part", ImVec2(MAIN_FRAME_SIZE_WIDTH_MIN, ImGui::GetContentRegionAvail().y));
{
// 拖拽输入区域 // 拖拽输入区域
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)); 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::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y))); Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));
@@ -51,9 +77,21 @@ void UI_Layout()
// 导出文件 // 导出文件
Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale)); 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)
+250
View File
@@ -0,0 +1,250 @@
#include "Workflow-Editor.hpp"
#include "imgui.h"
#include "imgui_internal.h"
#include "imnodes.h"
#include <algorithm>
// 构造函数
Workflow_Editor_Class::Workflow_Editor_Class() {}
// 析构函数
Workflow_Editor_Class::~Workflow_Editor_Class()
{
// 释放资源
for (auto &pNode : this->Node_List)
delete pNode;
}
// 客制化圆形带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;
}
// 消息行输入节点绘制函数
bool MsgLine_Input_Node_Class::show_and_get_state()
{
// 节点宽度
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++)
{
if ((*iterator)->show_and_get_state())
{
delete *iterator;
// 迭代器删除后会返回下一个位置的迭代器
iterator = this->Node_List.erase(iterator);
iterator--;
}
}
// 右键菜单
{
const bool open_popup = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
ImNodes::IsEditorHovered() &&
ImGui::IsMouseReleased(ImGuiMouseButton_Right);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
if (!ImGui::IsAnyItemHovered() && open_popup)
{
ImGui::OpenPopup("RightClick_Popup");
}
if (ImGui::BeginPopup("RightClick_Popup"))
{
ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup();
// 节点添加菜单
if (ImGui::BeginMenu("Add Nodes"))
{
if (ImGui::MenuItem("Msg input node."))
this->Add_Node(NODE_TYPE_MSG_LINE_INPUT, click_pos);
ImGui::EndMenu();
}
ImGui::EndPopup();
}
}
{
// ImNodes::BeginNode(1);
// ImNodes::BeginNodeTitleBar();
// // 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();
}
// 添加指定类型节点
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:
break;
}
// 重新排序确保后续ID分配正常
std::sort(this->Node_List.begin(),
this->Node_List.end(),
[](Node_Class *a, Node_Class *b) -> bool
{ return a->getID() < b->getID(); });
}