Line |
Branch |
Exec |
Source |
1 |
|
|
#pragma once |
2 |
|
|
|
3 |
|
|
#define IMGUI_DEFINE_MATH_OPERATORS |
4 |
|
|
#include <imgui.h> |
5 |
|
|
#include <imgui_internal.h> |
6 |
|
|
|
7 |
|
|
#include <string> |
8 |
|
|
#include <unordered_map> |
9 |
|
|
#include <vector> |
10 |
|
|
|
11 |
|
|
uint64_t nextid(); |
12 |
|
|
bool draw_bezier(ImDrawList* draw_list, |
13 |
|
|
ImVec2 p1, |
14 |
|
|
ImVec2 p2, |
15 |
|
|
ImU32 color, |
16 |
|
|
int segment, |
17 |
|
|
float tickness = 2, // |
18 |
|
|
float eps = 2 // |
19 |
|
|
); |
20 |
|
|
|
21 |
|
|
struct Base { |
22 |
|
|
uint64_t id; |
23 |
|
|
|
24 |
|
|
Base(): id(nextid()) {} |
25 |
|
|
}; |
26 |
|
|
|
27 |
|
|
enum class PinKind |
28 |
|
|
{ |
29 |
|
|
Flow, |
30 |
|
|
Circle, |
31 |
|
|
Square, |
32 |
|
|
Grid, |
33 |
|
|
RoundSquare, |
34 |
|
|
Diamond, |
35 |
|
|
}; |
36 |
|
|
|
37 |
|
|
enum class PinType |
38 |
|
|
{ |
39 |
|
|
Flow, |
40 |
|
|
Bool, |
41 |
|
|
Int, |
42 |
|
|
Float, |
43 |
|
|
String, |
44 |
|
|
Object, |
45 |
|
|
Delegate, |
46 |
|
|
}; |
47 |
|
|
|
48 |
|
|
struct Pin: public Base { |
49 |
|
|
std::string name; |
50 |
|
|
// std::string typename; |
51 |
|
|
PinType type = PinType::Object; |
52 |
|
|
PinKind kind = PinKind::Circle; |
53 |
|
|
ImVec2 pos; |
54 |
|
|
bool connected = false; |
55 |
|
|
|
56 |
|
|
// Inline value |
57 |
|
|
uint64_t value; |
58 |
|
|
float* as_float() { |
59 |
|
✗ |
return reinterpret_cast<float*>(&value); |
60 |
|
|
} |
61 |
|
|
}; |
62 |
|
|
|
63 |
|
|
struct Link { |
64 |
|
|
Link(Pin* from, Pin* to): from(from), to(to) { |
65 |
|
✗ |
from->connected = true; |
66 |
|
✗ |
to->connected = true; |
67 |
|
✗ |
} |
68 |
|
|
|
69 |
|
|
std::string name; |
70 |
|
|
|
71 |
|
|
Pin* from; |
72 |
|
|
Pin* to; |
73 |
|
|
}; |
74 |
|
|
|
75 |
|
|
struct Layout { |
76 |
|
|
ImVec2 input = ImVec2(120, 50); |
77 |
|
|
ImVec2 output = ImVec2(120, 50); |
78 |
|
|
}; |
79 |
|
|
|
80 |
|
|
// Expression |
81 |
|
|
struct Node: public Base { |
82 |
|
|
ImVec2 pos; |
83 |
|
|
ImVec2 size; |
84 |
|
|
std::string name; |
85 |
|
|
bool selected = false; |
86 |
|
|
|
87 |
|
|
std::vector<Pin> inputs; |
88 |
|
|
std::vector<Pin> outputs; |
89 |
|
|
|
90 |
|
|
Layout layout; |
91 |
|
|
|
92 |
|
|
// ----- |
93 |
|
|
Pin* exec_in() { |
94 |
|
✗ |
for(Pin& p : inputs) { |
95 |
|
✗ |
if (p.type == PinType::Flow) |
96 |
|
✗ |
return &p; |
97 |
|
|
} |
98 |
|
✗ |
return nullptr; |
99 |
|
|
} |
100 |
|
|
|
101 |
|
|
Pin* exec_out() { |
102 |
|
|
for(Pin& p : outputs) { |
103 |
|
|
if (p.type == PinType::Flow) |
104 |
|
|
return &p; |
105 |
|
|
} |
106 |
|
|
return nullptr; |
107 |
|
|
} |
108 |
|
|
}; |
109 |
|
|
|
110 |
|
|
// Statement |
111 |
|
|
// Function |
112 |
|
|
// Macro |
113 |
|
|
struct Tree: public Base { |
114 |
|
|
std::string name; |
115 |
|
|
|
116 |
|
|
std::vector<Node> nodes; |
117 |
|
|
std::vector<Link> links; |
118 |
|
|
}; |
119 |
|
|
|
120 |
|
|
// module |
121 |
|
|
// namespace |
122 |
|
|
struct Forest: public Base { |
123 |
|
|
|
124 |
|
|
std::vector<Tree> trees; |
125 |
|
|
}; |
126 |
|
|
|
127 |
|
|
struct GraphEditor: public Base { |
128 |
|
|
|
129 |
|
|
std::vector<Forest> forests; |
130 |
|
|
|
131 |
|
|
void draw(); |
132 |
|
|
|
133 |
|
|
void draw(Pin* pin, ImVec2 center); |
134 |
|
|
void draw(Link* link, ImVec2 offset); |
135 |
|
|
void draw(Node* node, ImVec2 offset); |
136 |
|
|
void drawgrid(); |
137 |
|
|
|
138 |
|
|
void handle_events(ImVec2 offset); |
139 |
|
|
|
140 |
|
|
// |
141 |
|
|
ImVec2 scrolling = ImVec2(0.0f, 0.0f); |
142 |
|
|
Node* hovered_node = nullptr; |
143 |
|
|
Node* selected_node = nullptr; |
144 |
|
|
Pin* hovered_pin = nullptr; |
145 |
|
|
Pin* selected_pin = nullptr; |
146 |
|
|
Link* hovered_link = nullptr; |
147 |
|
|
Tree* selected_tree = nullptr; |
148 |
|
|
Tree* current_tree = nullptr; |
149 |
|
|
std::unordered_map<PinType, ImU32> _colors = {{ |
150 |
|
|
{PinType::Flow, IM_COL32(255, 255, 255, 255)}, |
151 |
|
|
{PinType::Bool, IM_COL32(220, 48, 48, 255)}, |
152 |
|
|
{PinType::Int, IM_COL32(68, 201, 156, 255)}, |
153 |
|
|
{PinType::Float, IM_COL32(147, 226, 74, 255)}, |
154 |
|
|
{PinType::String, IM_COL32(124, 21, 153, 255)}, |
155 |
|
|
{PinType::Object, IM_COL32(51, 150, 215, 255)}, |
156 |
|
|
{PinType::Delegate, IM_COL32(255, 48, 48, 255)}, |
157 |
|
|
}}; |
158 |
|
|
|
159 |
|
|
// State |
160 |
|
|
float pin_label_margin = 5; |
161 |
|
|
float node_padding = 4.0f; |
162 |
|
|
float pin_radius = 12; |
163 |
|
|
int bezier_segments = 10; |
164 |
|
|
float tickness = 3; |
165 |
|
|
bool show_grid = true; |
166 |
|
|
bool open_context_menu = false; |
167 |
|
|
ImU32 node_bg_color = IM_COL32(75, 75, 75, 255); |
168 |
|
|
ImU32 node_outline_color = IM_COL32(100, 100, 100, 255); |
169 |
|
|
ImU32 node_selected_color= IM_COL32( 50, 50, 200, 255); |
170 |
|
|
ImU32 rectangle_color = IM_COL32(100, 100, 200, 125); |
171 |
|
|
bool rectangle_select = false; |
172 |
|
|
ImVec2 rectangle_start; |
173 |
|
|
ImRect rectangle_selection; |
174 |
|
|
|
175 |
|
|
std::unordered_map<Node*, bool> selected; |
176 |
|
|
|
177 |
|
|
ImRect _size; |
178 |
|
|
ImVec2 _offset; |
179 |
|
|
|
180 |
|
|
ImVec2 get_offset() { return _offset; } |
181 |
|
|
|
182 |
|
|
ImVec2 estimate_size(Node& node, ImVec2 font_size = ImVec2(7, 13)); |
183 |
|
|
|
184 |
|
|
bool is_selecting() const { |
185 |
|
✗ |
return rectangle_select; |
186 |
|
|
} |
187 |
|
|
ImVec2 with_scroll(ImVec2 pos) { |
188 |
|
✗ |
return pos + _offset; |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
bool has_selection() const { |
192 |
|
✗ |
return selected.size() > 0; |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
ImRect selection_rectangle() const { |
196 |
|
✗ |
return rectangle_selection; |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
void check_selected(Node* node) { |
200 |
|
✗ |
if (is_selecting()) { |
201 |
|
✗ |
if (selection_rectangle().Contains(ImRect(node->pos, node->size))) { |
202 |
|
✗ |
node->selected = true; |
203 |
|
✗ |
selected[node] = true; |
204 |
|
|
} |
205 |
|
|
else { |
206 |
|
✗ |
node->selected = false; |
207 |
|
✗ |
selected.extract(node); |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
✗ |
} |
211 |
|
|
|
212 |
|
|
private: |
213 |
|
|
struct PinStyle { |
214 |
|
|
PinKind kind; |
215 |
|
|
bool filled; |
216 |
|
|
ImU32 color; |
217 |
|
|
ImU32 fill; |
218 |
|
|
}; |
219 |
|
|
|
220 |
|
|
void draw(PinStyle& style, ImVec2 pos, ImVec2 size); |
221 |
|
|
void draw_flow(PinStyle& style, ImVec2 pos, ImVec2 size); |
222 |
|
|
void draw_circle(PinStyle& style, ImVec2 pos, ImVec2 size); |
223 |
|
|
void draw_square(PinStyle& style, ImVec2 pos, ImVec2 size); |
224 |
|
|
void draw_grid(PinStyle& style, ImVec2 pos, ImVec2 size); |
225 |
|
|
void draw_round_square(PinStyle& style, ImVec2 pos, ImVec2 size); |
226 |
|
|
void draw_diamond(PinStyle& style, ImVec2 pos, ImVec2 size); |
227 |
|
|
void draw_triangle(PinStyle& style, ImVec2 pos, ImVec2 size); |
228 |
|
|
}; |
229 |
|
|
|
230 |
|
|
|
231 |
|
|
|
232 |
|
|
struct TreeBuilder { |
233 |
|
|
TreeBuilder(Tree& t): |
234 |
|
|
tree(t) |
235 |
|
|
{} |
236 |
|
|
|
237 |
|
|
Node& mew_node() { |
238 |
|
|
Node& n = tree.nodes.emplace_back(); |
239 |
|
|
return n; |
240 |
|
|
} |
241 |
|
|
|
242 |
|
|
Tree& tree; |
243 |
|
|
}; |
244 |
|
|
|
245 |
|
|
struct GraphBuilder { |
246 |
|
|
GraphBuilder(GraphEditor& ed): |
247 |
|
|
editor(ed) |
248 |
|
|
{} |
249 |
|
|
|
250 |
|
|
|
251 |
|
|
|
252 |
|
|
GraphEditor& editor; |
253 |
|
|
}; |
254 |
|
|
|