378 lines
11 KiB
C++
378 lines
11 KiB
C++
#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;
|
||
}; |