311 lines
7.8 KiB
C++
311 lines
7.8 KiB
C++
//------------------------------------------------------------------------------
|
|
// LICENSE
|
|
// This software is dual-licensed to the public domain and under the following
|
|
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
|
// publish, and distribute this file as you see fit.
|
|
//
|
|
// CREDITS
|
|
// Written by Michal Cichon
|
|
//------------------------------------------------------------------------------
|
|
# define IMGUI_DEFINE_MATH_OPERATORS
|
|
# include "builders.h"
|
|
# include <imgui_internal.h>
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
namespace ed = ax::NodeEditor;
|
|
namespace util = ax::NodeEditor::Utilities;
|
|
|
|
util::BlueprintNodeBuilder::BlueprintNodeBuilder(ImTextureID texture, int textureWidth, int textureHeight):
|
|
HeaderTextureId(texture),
|
|
HeaderTextureWidth(textureWidth),
|
|
HeaderTextureHeight(textureHeight),
|
|
CurrentNodeId(0),
|
|
CurrentStage(Stage::Invalid),
|
|
HasHeader(false)
|
|
{
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Begin(ed::NodeId id)
|
|
{
|
|
HasHeader = false;
|
|
HeaderMin = HeaderMax = ImVec2();
|
|
|
|
ed::PushStyleVar(StyleVar_NodePadding, ImVec4(8, 4, 8, 8));
|
|
|
|
ed::BeginNode(id);
|
|
|
|
ImGui::PushID(id.AsPointer());
|
|
CurrentNodeId = id;
|
|
|
|
SetStage(Stage::Begin);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::End()
|
|
{
|
|
SetStage(Stage::End);
|
|
|
|
ed::EndNode();
|
|
|
|
if (ImGui::IsItemVisible())
|
|
{
|
|
auto alpha = static_cast<int>(255 * ImGui::GetStyle().Alpha);
|
|
|
|
auto drawList = ed::GetNodeBackgroundDrawList(CurrentNodeId);
|
|
|
|
const auto halfBorderWidth = ed::GetStyle().NodeBorderWidth * 0.5f;
|
|
|
|
auto headerColor = IM_COL32(0, 0, 0, alpha) | (HeaderColor & IM_COL32(255, 255, 255, 0));
|
|
if ((HeaderMax.x > HeaderMin.x) && (HeaderMax.y > HeaderMin.y) && HeaderTextureId)
|
|
{
|
|
const auto uv = ImVec2(
|
|
(HeaderMax.x - HeaderMin.x) / (float)(4.0f * HeaderTextureWidth),
|
|
(HeaderMax.y - HeaderMin.y) / (float)(4.0f * HeaderTextureHeight));
|
|
|
|
drawList->AddImageRounded(HeaderTextureId,
|
|
HeaderMin - ImVec2(8 - halfBorderWidth, 4 - halfBorderWidth),
|
|
HeaderMax + ImVec2(8 - halfBorderWidth, 0),
|
|
ImVec2(0.0f, 0.0f), uv,
|
|
#if IMGUI_VERSION_NUM > 18101
|
|
headerColor, GetStyle().NodeRounding, ImDrawFlags_RoundCornersTop);
|
|
#else
|
|
headerColor, GetStyle().NodeRounding, 1 | 2);
|
|
#endif
|
|
|
|
if (ContentMin.y > HeaderMax.y)
|
|
{
|
|
drawList->AddLine(
|
|
ImVec2(HeaderMin.x - (8 - halfBorderWidth), HeaderMax.y - 0.5f),
|
|
ImVec2(HeaderMax.x + (8 - halfBorderWidth), HeaderMax.y - 0.5f),
|
|
ImColor(255, 255, 255, 96 * alpha / (3 * 255)), 1.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
CurrentNodeId = 0;
|
|
|
|
ImGui::PopID();
|
|
|
|
ed::PopStyleVar();
|
|
|
|
SetStage(Stage::Invalid);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Header(const ImVec4& color)
|
|
{
|
|
HeaderColor = ImColor(color);
|
|
SetStage(Stage::Header);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::EndHeader()
|
|
{
|
|
SetStage(Stage::Content);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Input(ed::PinId id)
|
|
{
|
|
if (CurrentStage == Stage::Begin)
|
|
SetStage(Stage::Content);
|
|
|
|
const auto applyPadding = (CurrentStage == Stage::Input);
|
|
|
|
SetStage(Stage::Input);
|
|
|
|
if (applyPadding)
|
|
ImGui::Spring(0);
|
|
|
|
Pin(id, PinKind::Input);
|
|
|
|
ImGui::BeginHorizontal(id.AsPointer());
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::EndInput()
|
|
{
|
|
ImGui::EndHorizontal();
|
|
|
|
EndPin();
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Middle()
|
|
{
|
|
if (CurrentStage == Stage::Begin)
|
|
SetStage(Stage::Content);
|
|
|
|
SetStage(Stage::Middle);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Output(ed::PinId id)
|
|
{
|
|
if (CurrentStage == Stage::Begin)
|
|
SetStage(Stage::Content);
|
|
|
|
const auto applyPadding = (CurrentStage == Stage::Output);
|
|
|
|
SetStage(Stage::Output);
|
|
|
|
if (applyPadding)
|
|
ImGui::Spring(0);
|
|
|
|
Pin(id, PinKind::Output);
|
|
|
|
ImGui::BeginHorizontal(id.AsPointer());
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::EndOutput()
|
|
{
|
|
ImGui::EndHorizontal();
|
|
|
|
EndPin();
|
|
}
|
|
|
|
bool util::BlueprintNodeBuilder::SetStage(Stage stage)
|
|
{
|
|
if (stage == CurrentStage)
|
|
return false;
|
|
|
|
auto oldStage = CurrentStage;
|
|
CurrentStage = stage;
|
|
|
|
ImVec2 cursor;
|
|
switch (oldStage)
|
|
{
|
|
case Stage::Begin:
|
|
break;
|
|
|
|
case Stage::Header:
|
|
ImGui::EndHorizontal();
|
|
HeaderMin = ImGui::GetItemRectMin();
|
|
HeaderMax = ImGui::GetItemRectMax();
|
|
|
|
// spacing between header and content
|
|
ImGui::Spring(0, ImGui::GetStyle().ItemSpacing.y * 2.0f);
|
|
|
|
break;
|
|
|
|
case Stage::Content:
|
|
break;
|
|
|
|
case Stage::Input:
|
|
ed::PopStyleVar(2);
|
|
|
|
ImGui::Spring(1, 0);
|
|
ImGui::EndVertical();
|
|
|
|
// #debug
|
|
// ImGui::GetWindowDrawList()->AddRect(
|
|
// ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
|
|
|
|
break;
|
|
|
|
case Stage::Middle:
|
|
ImGui::EndVertical();
|
|
|
|
// #debug
|
|
// ImGui::GetWindowDrawList()->AddRect(
|
|
// ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
|
|
|
|
break;
|
|
|
|
case Stage::Output:
|
|
ed::PopStyleVar(2);
|
|
|
|
ImGui::Spring(1, 0);
|
|
ImGui::EndVertical();
|
|
|
|
// #debug
|
|
// ImGui::GetWindowDrawList()->AddRect(
|
|
// ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
|
|
|
|
break;
|
|
|
|
case Stage::End:
|
|
break;
|
|
|
|
case Stage::Invalid:
|
|
break;
|
|
}
|
|
|
|
switch (stage)
|
|
{
|
|
case Stage::Begin:
|
|
ImGui::BeginVertical("node");
|
|
break;
|
|
|
|
case Stage::Header:
|
|
HasHeader = true;
|
|
|
|
ImGui::BeginHorizontal("header");
|
|
break;
|
|
|
|
case Stage::Content:
|
|
if (oldStage == Stage::Begin)
|
|
ImGui::Spring(0);
|
|
|
|
ImGui::BeginHorizontal("content");
|
|
ImGui::Spring(0, 0);
|
|
break;
|
|
|
|
case Stage::Input:
|
|
ImGui::BeginVertical("inputs", ImVec2(0, 0), 0.0f);
|
|
|
|
ed::PushStyleVar(ed::StyleVar_PivotAlignment, ImVec2(0, 0.5f));
|
|
ed::PushStyleVar(ed::StyleVar_PivotSize, ImVec2(0, 0));
|
|
|
|
if (!HasHeader)
|
|
ImGui::Spring(1, 0);
|
|
break;
|
|
|
|
case Stage::Middle:
|
|
ImGui::Spring(1);
|
|
ImGui::BeginVertical("middle", ImVec2(0, 0), 1.0f);
|
|
break;
|
|
|
|
case Stage::Output:
|
|
if (oldStage == Stage::Middle || oldStage == Stage::Input)
|
|
ImGui::Spring(1);
|
|
else
|
|
ImGui::Spring(1, 0);
|
|
ImGui::BeginVertical("outputs", ImVec2(0, 0), 1.0f);
|
|
|
|
ed::PushStyleVar(ed::StyleVar_PivotAlignment, ImVec2(1.0f, 0.5f));
|
|
ed::PushStyleVar(ed::StyleVar_PivotSize, ImVec2(0, 0));
|
|
|
|
if (!HasHeader)
|
|
ImGui::Spring(1, 0);
|
|
break;
|
|
|
|
case Stage::End:
|
|
if (oldStage == Stage::Input)
|
|
ImGui::Spring(1, 0);
|
|
if (oldStage != Stage::Begin)
|
|
ImGui::EndHorizontal();
|
|
ContentMin = ImGui::GetItemRectMin();
|
|
ContentMax = ImGui::GetItemRectMax();
|
|
|
|
//ImGui::Spring(0);
|
|
ImGui::EndVertical();
|
|
NodeMin = ImGui::GetItemRectMin();
|
|
NodeMax = ImGui::GetItemRectMax();
|
|
break;
|
|
|
|
case Stage::Invalid:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::Pin(ed::PinId id, ed::PinKind kind)
|
|
{
|
|
ed::BeginPin(id, kind);
|
|
}
|
|
|
|
void util::BlueprintNodeBuilder::EndPin()
|
|
{
|
|
ed::EndPin();
|
|
|
|
// #debug
|
|
// ImGui::GetWindowDrawList()->AddRectFilled(
|
|
// ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 64));
|
|
}
|