6 #define IMGUI_DEFINE_MATH_OPERATORS
8 #include <imgui_internal.h>
14 GuiNode(std::string name
, Rect bbox
, uint n_slots_in
, uint n_slots_out
)
15 : name(name
), bbox(bbox
), n_slots_in(n_slots_in
), n_slots_out(n_slots_out
)
23 ImVec2
slot_location(SlotDirection direction
, uint i
) const {
27 n_slots
= n_slots_in
; break;
29 n_slots
= n_slots_out
; break;
32 auto x_stride
= bbox
.size
.y
/(n_slots
+1);
37 base
= bbox
.pos
; break;
39 base
= bbox
.pos
+ ImVec2(bbox
.size
.x
, 0); break;
42 return base
+ ImVec2(0, (i
+ 1) * x_stride
);
54 GuiEdge(GuiNode
*lhs
, GuiNode
*rhs
, uint fromSlot
, uint toSlot
)
55 : lhs(lhs
), rhs(rhs
), fromSlot(fromSlot
), toSlot(toSlot
) {}
67 nodeList
.emplace_back("hi", Rect(10, 10, 60, 60), 3, 1);
68 nodeList
.emplace_back("hi2", Rect(80, 10, 60, 60), 1, 1);
70 edgeList
.emplace_back(&nodeList
[0], &nodeList
[1], 0, 0);
73 void draw_window(const char *title
, bool *opened
) {
74 ImGui::SetNextWindowSize(ImVec2(700,600), ImGuiSetCond_FirstUseEver
);
75 if (ImGui::Begin(title
, opened
)) {
76 // -- Create child canvas
77 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(1,1));
78 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding
, ImVec2(0,0));
79 ImGui::PushStyleColor(ImGuiCol_ChildWindowBg
, ImColor(60,60,70,200));
80 ImGui::BeginChild("nodes_region", ImVec2(0, 0), true, ImGuiWindowFlags_NoScrollbar
|ImGuiWindowFlags_NoMove
);
83 // Get the draw list for this canvas
84 ImDrawList
* draw_list
= ImGui::GetWindowDrawList();
85 draw_list
->ChannelsSplit(2);
87 // this gets the offset to the upper-right corner of the child canvas.
88 // Note: here, cursor means "draw cursor", not "mouse pointing cursor".
89 ImVec2 canvas_pos
= ImGui::GetCursorScreenPos();
90 ImVec2 canvas_size
= ImGui::GetWindowSize();
92 ImVec2 offset
= canvas_pos
- scrolling
; // TODO: add scrolling
95 draw_list
->ChannelsSetCurrent(0);
97 ImVec2 local_offset
= ImGui::GetCursorPos() - scrolling
;
99 float spacing
= 32.0f
; ImU32 color
= IM_COL32(200, 200, 200, 40);
101 for (float x
= fmodf(local_offset
.x
, spacing
); x
< canvas_size
.x
; x
+= spacing
)
102 draw_list
->AddLine(ImVec2(x
, 0.0f
)+canvas_pos
,
103 ImVec2(x
, canvas_size
.y
)+canvas_pos
, color
);
104 for (float y
= fmodf(local_offset
.y
, spacing
); y
< canvas_size
.y
; y
+= spacing
)
105 draw_list
->AddLine(ImVec2(0.0f
, y
)+canvas_pos
,
106 ImVec2(canvas_size
.x
, y
)+canvas_pos
, color
);
110 draw_list
->ChannelsSetCurrent(0);
111 for (const auto &edge
: edgeList
) {
112 auto head
= offset
+ edge
.lhs
->slot_location(GuiNode::OUT
, edge
.fromSlot
);
113 auto tail
= offset
+ edge
.rhs
->slot_location(GuiNode::IN
, edge
.fromSlot
);
115 draw_list
->AddBezierCurve(head
, head
+ImVec2(50, 0),
116 tail
+ImVec2(-50, 0), tail
,
117 ImColor(200, 200, 200), 3.0f
);
120 Rect viewportRect
= Rect(scrolling
, canvas_size
);
122 for (auto &node
: nodeList
) {
123 bool visible
= viewportRect
.intersects(node
.bbox
);
125 // TODO: this is garbage
126 ImGui::PushID((void *)&node
);
128 // -- Draw the node boxes
129 draw_list
->ChannelsSetCurrent(0); // Switch to the background layer
131 // draw an invisible button in the background, for dragging/hovering
132 ImGui::SetCursorScreenPos(offset
+ node
.bbox
.pos
);
133 ImGui::InvisibleButton("node", node
.bbox
.size
);
135 if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0))
136 node
.bbox
.pos
+= ImGui::GetIO().MouseDelta
;
138 ImVec2 upper_left
= offset
+ node
.bbox
.pos
;
139 ImVec2 lower_right
= upper_left
+ node
.bbox
.size
;
141 draw_list
->AddRectFilled(upper_left
, lower_right
, ImColor(60, 60, 60), 4.0f
);
142 draw_list
->AddRect(upper_left
, lower_right
, ImColor(100, 100, 100), 4.0f
);
144 // -- Draw the connection dots
145 for (int i
=0; i
<node
.n_slots_in
; i
++) {
146 auto position
= node
.slot_location(GuiNode::IN
, i
);
147 draw_list
->AddCircleFilled(offset
+ position
, 4.0f
, ImColor(150, 150, 150, 150));
150 for (int i
=0; i
<node
.n_slots_out
; i
++) {
151 auto position
= node
.slot_location(GuiNode::OUT
, i
);
152 draw_list
->AddCircleFilled(offset
+ position
, 4.0f
, ImColor(150, 150, 150, 150));
159 // -- merge channels back together
160 draw_list
->ChannelsMerge();
163 // [ pointer over neditor ] [ not interacting ctrls ] [ middle mouse dragging ]
164 if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(2, 0.0f
))
165 scrolling
= scrolling
- ImGui::GetIO().MouseDelta
;
168 ImGui::EndChild(); // end :nodes_region
169 ImGui::PopStyleColor(); // pop ChildWindowBg
170 ImGui::PopStyleVar(2); // pop FramePadding, WindowPadding
176 std::vector
<GuiNode
> nodeList
;
177 std::vector
<GuiEdge
> edgeList
;
179 ImVec2 scrolling
= ImVec2(0.0f
, 0.0f
);
180 bool show_grid
= true;