0.4.1
Loading...
Searching...
No Matches
BlueprintNodeBuilder.cpp
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// LICENSE
3// This software is dual-licensed to the public domain and under the following
4// license: you are granted a perpetual, irrevocable license to copy, modify,
5// publish, and distribute this file as you see fit.
6//
7// CREDITS
8// Written by Michal Cichon
9//------------------------------------------------------------------------------
11#include <imgui_internal.h>
12
13//------------------------------------------------------------------------------
14
15ax::NodeEditor::Utilities::BlueprintNodeBuilder::BlueprintNodeBuilder(ImTextureID texture, int textureWidth, int textureHeight)
16 : HeaderTextureId(texture), HeaderTextureWidth(textureWidth), HeaderTextureHeight(textureHeight) {}
17
19{
20 HasHeader = false;
21 HeaderMin = HeaderMax = ImVec2();
22
23 ax::NodeEditor::PushStyleVar(StyleVar_NodePadding, ImVec4(8, 4, 8, 8));
24
25 ax::NodeEditor::BeginNode(id);
26
27 ImGui::PushID(id.AsPointer());
28 CurrentNodeId = id;
29
31}
32
34{
36
37 ax::NodeEditor::EndNode();
38
39 if (ImGui::IsItemVisible())
40 {
41 auto alpha = static_cast<int>(255 * ImGui::GetStyle().Alpha);
42
43 auto* drawList = ax::NodeEditor::GetNodeBackgroundDrawList(CurrentNodeId);
44
45 const auto halfBorderWidth = ax::NodeEditor::GetStyle().NodeBorderWidth * 0.5F;
46
47 auto headerColor = IM_COL32(0, 0, 0, alpha) | (HeaderColor & IM_COL32(255, 255, 255, 0));
48 if ((HeaderMax.x > HeaderMin.x) && (HeaderMax.y > HeaderMin.y) && HeaderTextureId)
49 {
50 const auto uv = ImVec2(
51 (HeaderMax.x - HeaderMin.x) / (4.0F * static_cast<float>(HeaderTextureWidth)),
52 (HeaderMax.y - HeaderMin.y) / (4.0F * static_cast<float>(HeaderTextureHeight)));
53
54 drawList->AddImageRounded(HeaderTextureId,
55 HeaderMin - ImVec2(8 - halfBorderWidth, 4 - halfBorderWidth),
56 HeaderMax + ImVec2(8 - halfBorderWidth, 0),
57 ImVec2(0.0F, 0.0F), uv,
58 headerColor, GetStyle().NodeRounding, 1 | 2);
59
60 auto headerSeparatorMin = ImVec2(HeaderMin.x, HeaderMax.y);
61 auto headerSeparatorMax = ImVec2(HeaderMax.x, HeaderMin.y);
62
63 if ((headerSeparatorMax.x > headerSeparatorMin.x) && (headerSeparatorMax.y > headerSeparatorMin.y))
64 {
65 drawList->AddLine(
66 headerSeparatorMin + ImVec2(-(8 - halfBorderWidth), -0.5F),
67 headerSeparatorMax + ImVec2((8 - halfBorderWidth), -0.5F),
68 ImColor(255, 255, 255, 96 * alpha / (3 * 255)), 1.0F);
69 }
70 }
71 }
72
73 CurrentNodeId = 0;
74
75 ImGui::PopID();
76
77 ax::NodeEditor::PopStyleVar();
78
80}
81
83{
84 HeaderColor = ImColor(color);
86}
87
92
94{
96 {
98 }
99
100 const auto applyPadding = (CurrentStage == Stage::Input);
101
103
104 if (applyPadding)
105 {
106 ImGui::Spring(0);
107 }
108
109 Pin(id, PinKind::Input);
110
111 ImGui::BeginHorizontal(id.AsPointer());
112}
113
115{
116 ImGui::EndHorizontal();
117
118 EndPin();
119}
120
130
132{
134 {
136 }
137
138 const auto applyPadding = (CurrentStage == Stage::Output);
139
141
142 if (applyPadding)
143 {
144 ImGui::Spring(0);
145 }
146
147 Pin(id, PinKind::Output);
148
149 ImGui::BeginHorizontal(id.AsPointer());
150}
151
153{
154 ImGui::EndHorizontal();
155
156 EndPin();
157}
158
160{
161 if (stage == CurrentStage)
162 {
163 return false;
164 }
165
166 auto oldStage = CurrentStage;
167 CurrentStage = stage;
168
169 switch (oldStage)
170 {
171 case Stage::Begin:
172 break;
173
174 case Stage::Header:
175 ImGui::EndHorizontal();
176 HeaderMin = ImGui::GetItemRectMin();
177 HeaderMax = ImGui::GetItemRectMax();
178
179 // spacing between header and content
180 ImGui::Spring(0, ImGui::GetStyle().ItemSpacing.y * 2.0F);
181
182 break;
183
184 case Stage::Content:
185 break;
186
187 case Stage::Input:
188 ax::NodeEditor::PopStyleVar(2);
189
190 ImGui::Spring(1, 0);
191 ImGui::EndVertical();
192
193 // #debug
194 // ImGui::GetWindowDrawList()->AddRect(
195 // ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
196
197 break;
198
199 case Stage::Middle:
200 ImGui::EndVertical();
201
202 // #debug
203 // ImGui::GetWindowDrawList()->AddRect(
204 // ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
205
206 break;
207
208 case Stage::Output:
209 ax::NodeEditor::PopStyleVar(2);
210
211 ImGui::Spring(1, 0);
212 ImGui::EndVertical();
213
214 // #debug
215 // ImGui::GetWindowDrawList()->AddRect(
216 // ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 255));
217
218 break;
219
220 case Stage::End:
221 // break;
222
223 case Stage::Invalid:
224 break;
225 }
226
227 switch (stage)
228 {
229 case Stage::Begin:
230 ImGui::BeginVertical("node");
231 break;
232
233 case Stage::Header:
234 HasHeader = true;
235
236 ImGui::BeginHorizontal("header");
237 break;
238
239 case Stage::Content:
240 if (oldStage == Stage::Begin)
241 {
242 ImGui::Spring(0);
243 }
244
245 ImGui::BeginHorizontal("content");
246 ImGui::Spring(0, 0);
247 break;
248
249 case Stage::Input:
250 ImGui::BeginVertical("inputs", ImVec2(0, 0), 0.0F);
251
252 ax::NodeEditor::PushStyleVar(ax::NodeEditor::StyleVar_PivotAlignment, ImVec2(0, 0.5F));
253 ax::NodeEditor::PushStyleVar(ax::NodeEditor::StyleVar_PivotSize, ImVec2(0, 0));
254
255 if (!HasHeader)
256 {
257 ImGui::Spring(1, 0);
258 }
259 break;
260
261 case Stage::Middle:
262 ImGui::Spring(1);
263 ImGui::BeginVertical("middle", ImVec2(0, 0), 1.0F);
264 break;
265
266 case Stage::Output:
267 if (oldStage == Stage::Middle || oldStage == Stage::Input)
268 {
269 ImGui::Spring(1);
270 }
271 else
272 {
273 ImGui::Spring(1, 0);
274 }
275 ImGui::BeginVertical("outputs", ImVec2(0, 0), 1.0F);
276
277 ax::NodeEditor::PushStyleVar(ax::NodeEditor::StyleVar_PivotAlignment, ImVec2(1.0F, 0.5F));
278 ax::NodeEditor::PushStyleVar(ax::NodeEditor::StyleVar_PivotSize, ImVec2(0, 0));
279
280 if (!HasHeader)
281 {
282 ImGui::Spring(1, 0);
283 }
284 break;
285
286 case Stage::End:
287 if (oldStage == Stage::Input)
288 {
289 ImGui::Spring(1, 0);
290 }
291 if (oldStage != Stage::Begin)
292 {
293 ImGui::EndHorizontal();
294 }
295 ContentMin = ImGui::GetItemRectMin();
296 ContentMax = ImGui::GetItemRectMax();
297
298 // ImGui::Spring(0);
299 ImGui::EndVertical();
300 NodeMin = ImGui::GetItemRectMin();
301 NodeMax = ImGui::GetItemRectMax();
302 break;
303
304 case Stage::Invalid:
305 break;
306 }
307
308 return true;
309}
310
311void ax::NodeEditor::Utilities::BlueprintNodeBuilder::Pin(ax::NodeEditor::PinId id, ax::NodeEditor::PinKind kind)
312{
313 ax::NodeEditor::BeginPin(id, kind);
314}
315
317{
318 ax::NodeEditor::EndPin();
319
320 // #debug
321 // ImGui::GetWindowDrawList()->AddRectFilled(
322 // ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 0, 0, 64));
323}
static void EndOutput()
Ends building the output pin.
NodeId CurrentNodeId
Id of the node currently built.
ImTextureID HeaderTextureId
Pointer to the texture to use for the header.
bool SetStage(Stage stage)
Set the stage of the node build process. Takes care of all the Layout elements.
void Middle()
Begins building of the middle of the node.
Stage CurrentStage
Current stage of the build process.
static void Pin(ax::NodeEditor::PinId id, ax::NodeEditor::PinKind kind)
Begins building a pin.
BlueprintNodeBuilder(ImTextureID texture=nullptr, int textureWidth=0, int textureHeight=0)
Constructor.
bool HasHeader
Flag whether the node has a header.
static void EndInput()
Ends building the input pin.