|
19 | 19 | {$IfDef FPC} |
20 | 20 | {$mode Delphi}{$H+} |
21 | 21 | {$ModeSwitch advancedrecords} |
| 22 | + //{$CODEALIGN LOCALMIN=16} |
| 23 | + {$inline on } |
22 | 24 | {$EndIf} |
23 | 25 |
|
24 | 26 | Interface |
25 | 27 |
|
26 | 28 | Uses |
27 | 29 | Generics.Collections, |
28 | 30 | SysUtils, |
29 | | - PasImGui, |
30 | | - PasImGui.Utils; |
| 31 | + PasImGui; |
31 | 32 |
|
32 | 33 | Type |
33 | 34 | { TNode } |
|
41 | 42 | InputsCount, OutputsCount: Integer; |
42 | 43 | Function GetInputSlotPos(slotNo: Integer): ImVec2; |
43 | 44 | Function GetOutputSlotPos(slotNo: Integer): ImVec2; |
44 | | - Constructor Create(id_: Integer; Const Name_: PAnsiChar; |
45 | | - pos_: ImVec2; Value_: Single; color_: ImVec4; inputsCount_, outputsCount_: Integer); |
| 45 | + Constructor Create(id_: Integer; Const Name_: PAnsiChar; pos_: ImVec2; Value_: Single; |
| 46 | + color_: ImVec4; inputsCount_, outputsCount_: Integer); |
46 | 47 | End; |
47 | 48 |
|
48 | 49 | { TNodeLink } |
|
64 | 65 | links: TList<TNodeLink>; |
65 | 66 | scrolling: ImVec2 = (x: 0.0; y: 0.0); |
66 | 67 | inited: Boolean = False; |
67 | | - show_grid: Boolean = False; |
| 68 | + show_grid: Boolean = True; |
68 | 69 | node_selected: Integer = -1; |
69 | 70 |
|
70 | 71 | Procedure ShowExampleAppCustomNodeGraph(opened: PBoolean); |
|
76 | 77 | offset, win_pos, canvas_sz, p1, p2, node_rect_min, node_rect_max, scene_pos: ImVec2; |
77 | 78 | draw_list: PImDrawList; |
78 | 79 | GRID_COLOR, node_bg_color: ImU32; |
79 | | - GRID_SZ, x, y: Single; |
| 80 | + x, y: Single; |
80 | 81 | old_any_active, node_widgets_active, node_moving_active: Boolean; |
81 | 82 | open_context_menu: Boolean; |
82 | 83 | node_hovered_in_list: Integer; |
83 | 84 | node_hovered_in_scene: Integer; |
84 | 85 | Const |
| 86 | + GRID_SZ : Single = 64.0; |
85 | 87 | NODE_SLOT_RADIUS: Single = 4.0; |
86 | 88 | NODE_WINDOW_PADDING: ImVec2 = (x: 8.0; y: 8.0); |
87 | 89 | Begin |
|
101 | 103 | links := TList<TNodeLink>.Create(); |
102 | 104 |
|
103 | 105 | nodes.Add(TNode.Create(0, 'MainTex', ImVec2.New(40, 50), 0.5, ImVec4.New(255, 100, 100), 1, 1)); |
104 | | - nodes.Add(TNode.Create(1, 'BumpMap', ImVec2.New(40, 150), 0.42, ImVec4.New(200, 100, 200), 1, 1)); |
105 | | - nodes.Add(TNode.Create(2, 'Combine', ImVec2.New(270, 80), 1.0, ImVec4.New(0, 200, 100), 2, 2)); |
| 106 | + nodes.Add(TNode.Create(1, 'BumpMap', ImVec2.New(40, 160), 0.42, ImVec4.New(200, 100, 200), 1, 1)); |
| 107 | + nodes.Add(TNode.Create(2, 'Combine', ImVec2.New(270, 80), 0.0, ImVec4.New(0, 200, 100), 2, 2)); |
106 | 108 | links.Add(TNodeLink.Create(0, 0, 2, 0)); |
107 | 109 | links.Add(TNodeLink.Create(1, 0, 2, 1)); |
108 | 110 |
|
|
113 | 115 | node_hovered_in_scene := -1; |
114 | 116 |
|
115 | 117 | // Draw a list of nodes on the left side |
116 | | - ImGui.BeginChild('node_list', ImVec2.New(100, 0)); |
| 118 | + ImGui.BeginChild('node_list', ImVec2.New(150, 0)); |
117 | 119 | ImGui.Text('Nodes'); |
118 | 120 | ImGui.Separator(); |
119 | 121 |
|
|
127 | 129 | If ImGui.IsItemHovered() Then |
128 | 130 | Begin |
129 | 131 | node_hovered_in_list := node.ID; |
130 | | - open_context_menu := Boolean(Ord(open_context_menu) Or |
131 | | - Ord(ImGui.IsMouseClicked(ImGuiMouseButton_Left))); |
| 132 | + open_context_menu := open_context_menu Or ImGui.IsMouseClicked(ImGuiMouseButton_Right); |
132 | 133 | End; |
133 | 134 | ImGui.PopID(); |
134 | 135 | End; |
|
138 | 139 | ImGui.BeginGroup(); |
139 | 140 |
|
140 | 141 | // Create our child canvas |
141 | | - ImGui.Text('Hold middle mouse button to scroll (%.2f,%.2f)',[scrolling.x, scrolling.y]); |
| 142 | + ImGui.Text('Hold middle mouse button to scroll (%.2f,%.2f)', [scrolling.x, scrolling.y]); |
142 | 143 | ImGui.SameLine(); |
143 | 144 | ImGui.Checkbox('Show grid', @show_grid); |
144 | 145 | ImGui.PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2.New(1, 1)); |
145 | 146 | ImGui.PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2.New(0, 0)); |
146 | 147 | ImGui.PushStyleColor(ImGuiCol_ChildBg, IM_COL32(60, 60, 70, 200)); |
147 | | - ImGui.BeginChild('scrolling_region', ImVec2.New(0, 0), ImGuiChildFlags_None, |
| 148 | + ImGui.BeginChild('scrolling_region', ImVec2.New(0, 0), ImGuiChildFlags_Border, |
148 | 149 | ImGuiWindowFlags_NoScrollbar Or ImGuiWindowFlags_NoMove); |
149 | 150 | ImGui.PopStyleVar(); // WindowPadding |
150 | 151 | ImGui.PushItemWidth(120.0); |
|
156 | 157 | If show_grid Then |
157 | 158 | Begin |
158 | 159 | GRID_COLOR := IM_COL32(200, 200, 200, 40); |
159 | | - GRID_SZ := 64.0; |
160 | 160 | win_pos := ImGui.GetCursorScreenPos(); |
161 | 161 | canvas_sz := ImGui.GetWindowSize(); |
162 | 162 |
|
163 | | - x := FMod(scrolling.x, GRID_SZ); |
164 | | - while x < canvas_sz.x do |
165 | | - begin |
| 163 | + x := Math.FMod(scrolling.x, GRID_SZ); |
| 164 | + While x < canvas_sz.x Do |
| 165 | + Begin |
166 | 166 | draw_list^.AddLine(ImVec2.New(x, 0.0) + win_pos, ImVec2.New(x, canvas_sz.y) + win_pos, GRID_COLOR); |
167 | | - x := x + GRID_SZ; |
168 | | - end; |
| 167 | + x += GRID_SZ; |
| 168 | + End; |
169 | 169 |
|
170 | | - y := fmod(scrolling.y, GRID_SZ); |
| 170 | + //y := scrolling.y - GRID_SZ * Int(scrolling.y/GRID_SZ); |
| 171 | + y := FMod(scrolling.y, GRID_SZ); |
171 | 172 | While y < canvas_sz.y Do |
172 | 173 | Begin |
173 | 174 | draw_list^.AddLine(ImVec2.New(0.0, y) + win_pos, ImVec2.New(canvas_sz.x, y) + win_pos, GRID_COLOR); |
174 | | - y := y + GRID_SZ; |
| 175 | + y += GRID_SZ; |
175 | 176 | End; |
176 | 177 | End; |
177 | 178 |
|
|
184 | 185 | link := links[link_idx]; |
185 | 186 | node_inp := nodes[link.InputIdx]; |
186 | 187 | node_out := nodes[link.OutputIdx]; |
| 188 | + |
| 189 | + node_out.Value += node_inp.Value; |
| 190 | + |
187 | 191 | p1 := offset + node_inp.GetOutputSlotPos(link.InputSlot); |
188 | 192 | p2 := offset + node_out.GetInputSlotPos(link.OutputSlot); |
189 | | - draw_list^.AddBezierCubic(p1, p1 + ImVec2.New(-50, 0), p2 + ImVec2.New(+50, 0), p2, IM_COL32(200, 200, 100, 255), 3.0); |
| 193 | + draw_list^.AddBezierCubic(p1, p1 + ImVec2.New(+50, 0), p2 + ImVec2.New(-50, 0), p2, IM_COL32(200, 200, 100, 255), 3.0); |
190 | 194 | End; |
191 | 195 |
|
192 | 196 | // Display nodes |
|
200 | 204 | // Display node contents first |
201 | 205 | draw_list^.ChannelsSetCurrent(1); // Foreground |
202 | 206 | old_any_active := ImGui.IsAnyItemActive(); |
| 207 | + |
203 | 208 | ImGui.SetCursorScreenPos(node_rect_min + NODE_WINDOW_PADDING); |
204 | 209 | ImGui.BeginGroup(); // Lock horizontal position |
205 | 210 | ImGui.Text('%s', [node.Name]); |
|
208 | 213 | ImGui.EndGroup(); |
209 | 214 |
|
210 | 215 | // Save the size of what we have emitted and whether any of the widgets are being used |
211 | | - node_widgets_active := (Not old_any_active And ImGui.IsAnyItemActive()); |
| 216 | + node_widgets_active := ((Not old_any_active) And ImGui.IsAnyItemActive()); |
212 | 217 | node.Size := ImGui.GetItemRectSize() + NODE_WINDOW_PADDING + NODE_WINDOW_PADDING; |
213 | 218 | node_rect_max := node_rect_min + node.Size; |
214 | 219 |
|
|
227 | 232 | node_selected := node.ID; |
228 | 233 |
|
229 | 234 | If (node_moving_active And ImGui.IsMouseDragging(ImGuiMouseButton_Left)) Then |
230 | | - node.Pos := node.Pos + io^.MouseDelta; |
| 235 | + node.Pos += io^.MouseDelta; |
231 | 236 |
|
232 | 237 | If ((node_hovered_in_list = node.ID) Or (node_hovered_in_scene = node.ID) Or |
233 | 238 | ((node_hovered_in_list = -1) And (node_selected = node.ID))) Then |
|
253 | 258 | // Open context menu |
254 | 259 | If ImGui.IsMouseReleased(ImGuiMouseButton_Right) Then |
255 | 260 | Begin |
256 | | - If ImGui.IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) Or |
257 | | - (Not ImGui.IsAnyItemHovered()) Then |
| 261 | + If ImGui.IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) Or (Not ImGui.IsAnyItemHovered()) Then |
258 | 262 | Begin |
| 263 | + node_selected := -1; |
259 | 264 | node_hovered_in_list := -1; |
260 | 265 | node_hovered_in_scene := -1; |
261 | | - node_selected := -1; |
262 | 266 | open_context_menu := True; |
263 | 267 | End; |
264 | 268 | End; |
| 269 | + |
265 | 270 | If open_context_menu Then |
266 | 271 | Begin |
267 | 272 | ImGui.OpenPopup('context_menu'); |
|
270 | 275 | If (node_hovered_in_scene <> -1) Then |
271 | 276 | node_selected := node_hovered_in_scene; |
272 | 277 | End; |
| 278 | + |
273 | 279 | // Draw context menu |
274 | 280 | ImGui.PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2.New(8, 8)); |
275 | 281 | If ImGui.BeginPopup('context_menu') Then |
|
294 | 300 | Else |
295 | 301 | Begin |
296 | 302 | If ImGui.MenuItem('Add') Then |
297 | | - nodes.Add(Node.Create(nodes.Count, 'New node', scene_pos, 0.5, |
298 | | - ImVec4.New(100, 100, 200), 2, 2)); |
| 303 | + nodes.Add(Node.Create(nodes.Count, 'New node', scene_pos, 0.5, ImVec4.New(100, 100, 200), 2, 2)); |
299 | 304 | If ImGui.MenuItem('Past', nil, False, False) Then |
300 | 305 | Begin |
301 | 306 | End; |
|
305 | 310 | ImGui.PopStyleVar(); |
306 | 311 |
|
307 | 312 | // Scrolling |
308 | | - If (ImGui.IsWindowHovered() And (Not ImGui.IsAnyItemActive()) And |
309 | | - ImGui.IsMouseDragging(ImGuiMouseButton_Middle, 0.0)) Then |
310 | | - scrolling := scrolling + io.MouseDelta; |
| 313 | + If (ImGui.IsWindowHovered() And (Not ImGui.IsAnyItemActive()) And ImGui.IsMouseDragging( |
| 314 | + ImGuiMouseButton_Middle, 0.0)) Then |
| 315 | + scrolling += io.MouseDelta; |
311 | 316 |
|
312 | 317 | ImGui.PopItemWidth(); |
313 | 318 | ImGui.EndChild(); |
|
323 | 328 | Function TNode.GetInputSlotPos(slotNo: Integer): ImVec2; |
324 | 329 | Begin |
325 | 330 | Result.x := Pos.x; |
326 | | - Result.y := Pos.y + Size.y * Single(slotNo + 1) / (Single(InputsCount) + 1); |
| 331 | + Result.y := Pos.y + Size.y * Single(slotNo + 1) / Single(InputsCount + 1); |
327 | 332 | End; |
328 | 333 |
|
329 | 334 | Function TNode.GetOutputSlotPos(slotNo: Integer): ImVec2; |
330 | 335 | Begin |
331 | 336 | Result.x := Pos.x + Size.x; |
332 | | - Result.y := Pos.y + Size.y * Single(slotNo + 1) / (Single(OutputsCount) + 1); |
| 337 | + Result.y := Pos.y + Size.y * Single(slotNo + 1) / Single(OutputsCount + 1); |
333 | 338 | End; |
334 | 339 |
|
335 | | -Constructor TNode.Create(id_: Integer; Const Name_: PAnsiChar; |
336 | | - pos_: ImVec2; Value_: Single; color_: ImVec4; inputsCount_, outputsCount_: Integer); |
| 340 | +Constructor TNode.Create(id_: Integer; Const Name_: PAnsiChar; pos_: ImVec2; Value_: Single; |
| 341 | + color_: ImVec4; inputsCount_, outputsCount_: Integer); |
337 | 342 | Begin |
338 | 343 | Self.ID := id_; |
339 | 344 | StrLCopy(Self.Name, name_, SizeOf(Self.Name) - 1); |
|
0 commit comments