DLT_Splitter/Src/Nodes_And_Connectors.cpp

378 lines
11 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
};