1 /*************************************************************************/
2 /* shader_graph_editor_plugin.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30 #include "shader_graph_editor_plugin.h"
31
32 #include "canvas_item_editor_plugin.h"
33 #include "os/keyboard.h"
34 #include "scene/gui/check_box.h"
35 #include "scene/gui/menu_button.h"
36 #include "scene/gui/panel.h"
37 #include "spatial_editor_plugin.h"
38
_input_event(const InputEvent & p_event)39 void GraphColorRampEdit::_input_event(const InputEvent &p_event) {
40
41 if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) {
42
43 points.remove(grabbed);
44 grabbed = -1;
45 update();
46 emit_signal("ramp_changed");
47 accept_event();
48 }
49
50 if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
51
52 update();
53 int x = p_event.mouse_button.x;
54 int total_w = get_size().width - get_size().height - 3;
55 if (x > total_w + 3) {
56
57 if (grabbed == -1)
58 return;
59 Size2 ms = Size2(350, picker->get_combined_minimum_size().height + 10);
60 picker->set_color(points[grabbed].color);
61 popup->set_pos(get_global_pos() - Size2(0, ms.height));
62 popup->set_size(ms);
63 popup->popup();
64 return;
65 }
66
67 float ofs = CLAMP(x / float(total_w), 0, 1);
68
69 grabbed = -1;
70 grabbing = true;
71 int pos = -1;
72 for (int i = 0; i < points.size(); i++) {
73
74 if (ABS(x - points[i].offset * total_w) < 4) {
75 grabbed = i;
76 }
77 if (points[i].offset < ofs)
78 pos = i;
79 }
80
81 grabbed_at = ofs;
82 //grab or select
83 if (grabbed != -1) {
84 return;
85 }
86 //insert
87
88 Point p;
89 p.offset = ofs;
90
91 Point prev;
92 Point next;
93
94 if (pos == -1) {
95
96 prev.color = Color(0, 0, 0);
97 prev.offset = 0;
98 if (points.size()) {
99 next = points[0];
100 } else {
101 next.color = Color(1, 1, 1);
102 next.offset = 1.0;
103 }
104 } else {
105
106 if (pos == points.size() - 1) {
107 next.color = Color(1, 1, 1);
108 next.offset = 1.0;
109 } else {
110 next = points[pos + 1];
111 }
112 prev = points[pos];
113 }
114
115 p.color = prev.color.linear_interpolate(next.color, (p.offset - prev.offset) / (next.offset - prev.offset));
116
117 points.push_back(p);
118 points.sort();
119 for (int i = 0; i < points.size(); i++) {
120 if (points[i].offset == ofs) {
121 grabbed = i;
122 break;
123 }
124 }
125
126 emit_signal("ramp_changed");
127 }
128
129 if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) {
130
131 if (grabbing) {
132 grabbing = false;
133 emit_signal("ramp_changed");
134 }
135 update();
136 }
137
138 if (p_event.type == InputEvent::MOUSE_MOTION && grabbing) {
139
140 int total_w = get_size().width - get_size().height - 3;
141
142 int x = p_event.mouse_motion.x;
143 float newofs = CLAMP(x / float(total_w), 0, 1);
144
145 bool valid = true;
146 for (int i = 0; i < points.size(); i++) {
147
148 if (points[i].offset == newofs && i != grabbed) {
149 valid = false;
150 }
151 }
152
153 if (!valid)
154 return;
155
156 points[grabbed].offset = newofs;
157
158 points.sort();
159 for (int i = 0; i < points.size(); i++) {
160 if (points[i].offset == newofs) {
161 grabbed = i;
162 break;
163 }
164 }
165
166 emit_signal("ramp_changed");
167
168 update();
169 }
170 }
171
_notification(int p_what)172 void GraphColorRampEdit::_notification(int p_what) {
173
174 if (p_what == NOTIFICATION_ENTER_TREE) {
175 if (!picker->is_connected("color_changed", this, "_color_changed")) {
176 picker->connect("color_changed", this, "_color_changed");
177 }
178 }
179 if (p_what == NOTIFICATION_DRAW) {
180
181 Point prev;
182 prev.offset = 0;
183 prev.color = Color(0, 0, 0);
184
185 int h = get_size().y;
186 int total_w = get_size().width - get_size().height - 3;
187
188 for (int i = -1; i < points.size(); i++) {
189
190 Point next;
191 if (i + 1 == points.size()) {
192 next.color = Color(1, 1, 1);
193 next.offset = 1;
194 } else {
195 next = points[i + 1];
196 }
197
198 if (prev.offset == next.offset) {
199 prev = next;
200 continue;
201 }
202
203 Vector<Vector2> points;
204 Vector<Color> colors;
205 points.push_back(Vector2(prev.offset * total_w, h));
206 points.push_back(Vector2(prev.offset * total_w, 0));
207 points.push_back(Vector2(next.offset * total_w, 0));
208 points.push_back(Vector2(next.offset * total_w, h));
209 colors.push_back(prev.color);
210 colors.push_back(prev.color);
211 colors.push_back(next.color);
212 colors.push_back(next.color);
213 draw_primitive(points, colors, Vector<Point2>());
214 prev = next;
215 }
216
217 for (int i = 0; i < points.size(); i++) {
218
219 Color col = i == grabbed ? Color(1, 0.0, 0.0, 0.9) : Color(1, 1, 1, 0.8);
220
221 draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h - 1), Color(0, 0, 0, 0.7));
222 draw_line(Vector2(points[i].offset * total_w - 1, h / 2), Vector2(points[i].offset * total_w - 1, h - 1), col);
223 draw_line(Vector2(points[i].offset * total_w + 1, h / 2), Vector2(points[i].offset * total_w + 1, h - 1), col);
224 draw_line(Vector2(points[i].offset * total_w - 1, h / 2), Vector2(points[i].offset * total_w + 1, h / 2), col);
225 draw_line(Vector2(points[i].offset * total_w - 1, h - 1), Vector2(points[i].offset * total_w + 1, h - 1), col);
226 }
227
228 if (grabbed != -1) {
229
230 draw_rect(Rect2(total_w + 3, 0, h, h), points[grabbed].color);
231 }
232
233 if (has_focus()) {
234
235 draw_line(Vector2(-1, -1), Vector2(total_w + 1, -1), Color(1, 1, 1, 0.6));
236 draw_line(Vector2(total_w + 1, -1), Vector2(total_w + 1, h + 1), Color(1, 1, 1, 0.6));
237 draw_line(Vector2(total_w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
238 draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
239 }
240 }
241 }
242
get_minimum_size() const243 Size2 GraphColorRampEdit::get_minimum_size() const {
244
245 return Vector2(0, 16);
246 }
247
_color_changed(const Color & p_color)248 void GraphColorRampEdit::_color_changed(const Color &p_color) {
249
250 if (grabbed == -1)
251 return;
252 points[grabbed].color = p_color;
253 update();
254 emit_signal("ramp_changed");
255 }
256
set_ramp(const Vector<float> & p_offsets,const Vector<Color> & p_colors)257 void GraphColorRampEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) {
258
259 ERR_FAIL_COND(p_offsets.size() != p_colors.size());
260 points.clear();
261 for (int i = 0; i < p_offsets.size(); i++) {
262 Point p;
263 p.offset = p_offsets[i];
264 p.color = p_colors[i];
265 points.push_back(p);
266 }
267
268 points.sort();
269 update();
270 }
271
get_offsets() const272 Vector<float> GraphColorRampEdit::get_offsets() const {
273 Vector<float> ret;
274 for (int i = 0; i < points.size(); i++)
275 ret.push_back(points[i].offset);
276 return ret;
277 }
get_colors() const278 Vector<Color> GraphColorRampEdit::get_colors() const {
279
280 Vector<Color> ret;
281 for (int i = 0; i < points.size(); i++)
282 ret.push_back(points[i].color);
283 return ret;
284 }
285
_bind_methods()286 void GraphColorRampEdit::_bind_methods() {
287
288 ObjectTypeDB::bind_method(_MD("_input_event"), &GraphColorRampEdit::_input_event);
289 ObjectTypeDB::bind_method(_MD("_color_changed"), &GraphColorRampEdit::_color_changed);
290 ADD_SIGNAL(MethodInfo("ramp_changed"));
291 }
292
GraphColorRampEdit()293 GraphColorRampEdit::GraphColorRampEdit() {
294
295 grabbed = -1;
296 grabbing = false;
297 set_focus_mode(FOCUS_ALL);
298
299 popup = memnew(PopupPanel);
300 picker = memnew(ColorPicker);
301 popup->add_child(picker);
302 popup->set_child_rect(picker);
303 add_child(popup);
304 }
305 ////////////
306
_input_event(const InputEvent & p_event)307 void GraphCurveMapEdit::_input_event(const InputEvent &p_event) {
308
309 if (p_event.type == InputEvent::KEY && p_event.key.pressed && p_event.key.scancode == KEY_DELETE && grabbed != -1) {
310
311 points.remove(grabbed);
312 grabbed = -1;
313 update();
314 emit_signal("curve_changed");
315 accept_event();
316 }
317
318 if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && p_event.mouse_button.pressed) {
319
320 update();
321 Point2 p = Vector2(p_event.mouse_button.x, p_event.mouse_button.y) / get_size();
322 p.y = 1.0 - p.y;
323 grabbed = -1;
324 grabbing = true;
325
326 for (int i = 0; i < points.size(); i++) {
327
328 Vector2 ps = p * get_size();
329 Vector2 pt = Vector2(points[i].offset, points[i].height) * get_size();
330 if (ps.distance_to(pt) < 4) {
331 grabbed = i;
332 }
333 }
334
335 //grab or select
336 if (grabbed != -1) {
337 return;
338 }
339 //insert
340
341 Point np;
342 np.offset = p.x;
343 np.height = p.y;
344
345 points.push_back(np);
346 points.sort();
347 for (int i = 0; i < points.size(); i++) {
348 if (points[i].offset == p.x && points[i].height == p.y) {
349 grabbed = i;
350 break;
351 }
352 }
353
354 emit_signal("curve_changed");
355 }
356
357 if (p_event.type == InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index == 1 && !p_event.mouse_button.pressed) {
358
359 if (grabbing) {
360 grabbing = false;
361 emit_signal("curve_changed");
362 }
363 update();
364 }
365
366 if (p_event.type == InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
367
368 Point2 p = Vector2(p_event.mouse_button.x, p_event.mouse_button.y) / get_size();
369 p.y = 1.0 - p.y;
370
371 p.x = CLAMP(p.x, 0.0, 1.0);
372 p.y = CLAMP(p.y, 0.0, 1.0);
373
374 bool valid = true;
375
376 for (int i = 0; i < points.size(); i++) {
377
378 if (points[i].offset == p.x && points[i].height == p.y && i != grabbed) {
379 valid = false;
380 }
381 }
382
383 if (!valid)
384 return;
385
386 points[grabbed].offset = p.x;
387 points[grabbed].height = p.y;
388
389 points.sort();
390 for (int i = 0; i < points.size(); i++) {
391 if (points[i].offset == p.x && points[i].height == p.y) {
392 grabbed = i;
393 break;
394 }
395 }
396
397 emit_signal("curve_changed");
398
399 update();
400 }
401 }
402
_plot_curve(const Vector2 & p_a,const Vector2 & p_b,const Vector2 & p_c,const Vector2 & p_d)403 void GraphCurveMapEdit::_plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d) {
404
405 float geometry[4][4];
406 float tmp1[4][4];
407 float tmp2[4][4];
408 float deltas[4][4];
409 double x, dx, dx2, dx3;
410 double y, dy, dy2, dy3;
411 double d, d2, d3;
412 int lastx, lasty;
413 int newx, newy;
414 int ntimes;
415 int i, j;
416
417 int xmax = get_size().x;
418 int ymax = get_size().y;
419
420 /* construct the geometry matrix from the segment */
421 for (i = 0; i < 4; i++) {
422 geometry[i][2] = 0;
423 geometry[i][3] = 0;
424 }
425
426 geometry[0][0] = (p_a[0] * xmax);
427 geometry[1][0] = (p_b[0] * xmax);
428 geometry[2][0] = (p_c[0] * xmax);
429 geometry[3][0] = (p_d[0] * xmax);
430
431 geometry[0][1] = (p_a[1] * ymax);
432 geometry[1][1] = (p_b[1] * ymax);
433 geometry[2][1] = (p_c[1] * ymax);
434 geometry[3][1] = (p_d[1] * ymax);
435
436 /* subdivide the curve ntimes (1000) times */
437 ntimes = 4 * xmax;
438 /* ntimes can be adjusted to give a finer or coarser curve */
439 d = 1.0 / ntimes;
440 d2 = d * d;
441 d3 = d * d * d;
442
443 /* construct a temporary matrix for determining the forward differencing deltas */
444 tmp2[0][0] = 0;
445 tmp2[0][1] = 0;
446 tmp2[0][2] = 0;
447 tmp2[0][3] = 1;
448 tmp2[1][0] = d3;
449 tmp2[1][1] = d2;
450 tmp2[1][2] = d;
451 tmp2[1][3] = 0;
452 tmp2[2][0] = 6 * d3;
453 tmp2[2][1] = 2 * d2;
454 tmp2[2][2] = 0;
455 tmp2[2][3] = 0;
456 tmp2[3][0] = 6 * d3;
457 tmp2[3][1] = 0;
458 tmp2[3][2] = 0;
459 tmp2[3][3] = 0;
460
461 /* compose the basis and geometry matrices */
462
463 static const float CR_basis[4][4] = {
464 { -0.5, 1.5, -1.5, 0.5 },
465 { 1.0, -2.5, 2.0, -0.5 },
466 { -0.5, 0.0, 0.5, 0.0 },
467 { 0.0, 1.0, 0.0, 0.0 },
468 };
469
470 for (i = 0; i < 4; i++) {
471 for (j = 0; j < 4; j++) {
472 tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] +
473 CR_basis[i][1] * geometry[1][j] +
474 CR_basis[i][2] * geometry[2][j] +
475 CR_basis[i][3] * geometry[3][j]);
476 }
477 }
478 /* compose the above results to get the deltas matrix */
479
480 for (i = 0; i < 4; i++) {
481 for (j = 0; j < 4; j++) {
482 deltas[i][j] = (tmp2[i][0] * tmp1[0][j] +
483 tmp2[i][1] * tmp1[1][j] +
484 tmp2[i][2] * tmp1[2][j] +
485 tmp2[i][3] * tmp1[3][j]);
486 }
487 }
488
489 /* extract the x deltas */
490 x = deltas[0][0];
491 dx = deltas[1][0];
492 dx2 = deltas[2][0];
493 dx3 = deltas[3][0];
494
495 /* extract the y deltas */
496 y = deltas[0][1];
497 dy = deltas[1][1];
498 dy2 = deltas[2][1];
499 dy3 = deltas[3][1];
500
501 lastx = CLAMP(x, 0, xmax);
502 lasty = CLAMP(y, 0, ymax);
503
504 /* if (fix255)
505 {
506 cd->curve[cd->outline][lastx] = lasty;
507 }
508 else
509 {
510 cd->curve_ptr[cd->outline][lastx] = lasty;
511 if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax);
512 }
513 */
514 /* loop over the curve */
515 for (i = 0; i < ntimes; i++) {
516 /* increment the x values */
517 x += dx;
518 dx += dx2;
519 dx2 += dx3;
520
521 /* increment the y values */
522 y += dy;
523 dy += dy2;
524 dy2 += dy3;
525
526 newx = CLAMP((Math::round(x)), 0, xmax);
527 newy = CLAMP((Math::round(y)), 0, ymax);
528
529 /* if this point is different than the last one...then draw it */
530 if ((lastx != newx) || (lasty != newy)) {
531 #if 0
532 if(fix255)
533 {
534 /* use fixed array size (for the curve graph) */
535 cd->curve[cd->outline][newx] = newy;
536 }
537 else
538 {
539 /* use dynamic allocated curve_ptr (for the real curve) */
540 cd->curve_ptr[cd->outline][newx] = newy;
541
542 if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy);
543 }
544 #endif
545 draw_line(Vector2(lastx, ymax - lasty), Vector2(newx, ymax - newy), Color(0.8, 0.8, 0.8, 0.8), 2.0);
546 }
547
548 lastx = newx;
549 lasty = newy;
550 }
551 }
552
_notification(int p_what)553 void GraphCurveMapEdit::_notification(int p_what) {
554
555 if (p_what == NOTIFICATION_DRAW) {
556
557 draw_style_box(get_stylebox("bg", "Tree"), Rect2(Point2(), get_size()));
558
559 int w = get_size().x;
560 int h = get_size().y;
561
562 Vector2 prev = Vector2(0, 0);
563 Vector2 prev2 = Vector2(0, 0);
564
565 for (int i = -1; i < points.size(); i++) {
566
567 Vector2 next;
568 Vector2 next2;
569 if (i + 1 >= points.size()) {
570 next = Vector2(1, 1);
571 } else {
572 next = Vector2(points[i + 1].offset, points[i + 1].height);
573 }
574
575 if (i + 2 >= points.size()) {
576 next2 = Vector2(1, 1);
577 } else {
578 next2 = Vector2(points[i + 2].offset, points[i + 2].height);
579 }
580
581 /*if (i==-1 && prev.offset==next.offset) {
582 prev=next;
583 continue;
584 }*/
585
586 _plot_curve(prev2, prev, next, next2);
587
588 prev2 = prev;
589 prev = next;
590 }
591
592 for (int i = 0; i < points.size(); i++) {
593
594 Color col = i == grabbed ? Color(1, 0.0, 0.0, 0.9) : Color(1, 1, 1, 0.8);
595
596 draw_rect(Rect2(Vector2(points[i].offset, 1.0 - points[i].height) * get_size() - Vector2(2, 2), Vector2(5, 5)), col);
597 }
598
599 /* if (grabbed!=-1) {
600
601 draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color);
602 }
603 */
604 if (has_focus()) {
605
606 draw_line(Vector2(-1, -1), Vector2(w + 1, -1), Color(1, 1, 1, 0.6));
607 draw_line(Vector2(w + 1, -1), Vector2(w + 1, h + 1), Color(1, 1, 1, 0.6));
608 draw_line(Vector2(w + 1, h + 1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
609 draw_line(Vector2(-1, -1), Vector2(-1, h + 1), Color(1, 1, 1, 0.6));
610 }
611 }
612 }
613
get_minimum_size() const614 Size2 GraphCurveMapEdit::get_minimum_size() const {
615
616 return Vector2(64, 64);
617 }
618
set_points(const Vector<Vector2> & p_points)619 void GraphCurveMapEdit::set_points(const Vector<Vector2> &p_points) {
620
621 points.clear();
622 for (int i = 0; i < p_points.size(); i++) {
623 Point p;
624 p.offset = p_points[i].x;
625 p.height = p_points[i].y;
626 points.push_back(p);
627 }
628
629 points.sort();
630 update();
631 }
632
get_points() const633 Vector<Vector2> GraphCurveMapEdit::get_points() const {
634 Vector<Vector2> ret;
635 for (int i = 0; i < points.size(); i++)
636 ret.push_back(Vector2(points[i].offset, points[i].height));
637 return ret;
638 }
639
_bind_methods()640 void GraphCurveMapEdit::_bind_methods() {
641
642 ObjectTypeDB::bind_method(_MD("_input_event"), &GraphCurveMapEdit::_input_event);
643 ADD_SIGNAL(MethodInfo("curve_changed"));
644 }
645
GraphCurveMapEdit()646 GraphCurveMapEdit::GraphCurveMapEdit() {
647
648 grabbed = -1;
649 grabbing = false;
650 set_focus_mode(FOCUS_ALL);
651 }
652
653 ////cbacks
654 ///
_scalar_const_changed(double p_value,int p_id)655 void ShaderGraphView::_scalar_const_changed(double p_value, int p_id) {
656
657 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
658 ur->create_action(TTR("Change Scalar Constant"), UndoRedo::MERGE_ENDS);
659 ur->add_do_method(graph.ptr(), "scalar_const_node_set_value", type, p_id, p_value);
660 ur->add_undo_method(graph.ptr(), "scalar_const_node_set_value", type, p_id, graph->scalar_const_node_get_value(type, p_id));
661 ur->add_do_method(this, "_update_graph");
662 ur->add_undo_method(this, "_update_graph");
663 block_update = true;
664 ur->commit_action();
665 block_update = false;
666 }
667
_vec_const_changed(double p_value,int p_id,Array p_arr)668 void ShaderGraphView::_vec_const_changed(double p_value, int p_id, Array p_arr) {
669
670 Vector3 val;
671 for (int i = 0; i < p_arr.size(); i++) {
672 val[i] = p_arr[i].call("get_val");
673 }
674
675 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
676 ur->create_action(TTR("Change Vec Constant"), UndoRedo::MERGE_ENDS);
677 ur->add_do_method(graph.ptr(), "vec_const_node_set_value", type, p_id, val);
678 ur->add_undo_method(graph.ptr(), "vec_const_node_set_value", type, p_id, graph->vec_const_node_get_value(type, p_id));
679 ur->add_do_method(this, "_update_graph");
680 ur->add_undo_method(this, "_update_graph");
681 block_update = true;
682 ur->commit_action();
683 block_update = false;
684 }
_rgb_const_changed(const Color & p_color,int p_id)685 void ShaderGraphView::_rgb_const_changed(const Color &p_color, int p_id) {
686
687 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
688 ur->create_action(TTR("Change RGB Constant"), UndoRedo::MERGE_ENDS);
689 ur->add_do_method(graph.ptr(), "rgb_const_node_set_value", type, p_id, p_color);
690 ur->add_undo_method(graph.ptr(), "rgb_const_node_set_value", type, p_id, graph->rgb_const_node_get_value(type, p_id));
691 ur->add_do_method(this, "_update_graph");
692 ur->add_undo_method(this, "_update_graph");
693 block_update = true;
694 ur->commit_action();
695 block_update = false;
696 }
_scalar_op_changed(int p_op,int p_id)697 void ShaderGraphView::_scalar_op_changed(int p_op, int p_id) {
698
699 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
700 ur->create_action(TTR("Change Scalar Operator"));
701 ur->add_do_method(graph.ptr(), "scalar_op_node_set_op", type, p_id, p_op);
702 ur->add_undo_method(graph.ptr(), "scalar_op_node_set_op", type, p_id, graph->scalar_op_node_get_op(type, p_id));
703 ur->add_do_method(this, "_update_graph");
704 ur->add_undo_method(this, "_update_graph");
705 block_update = true;
706 ur->commit_action();
707 block_update = false;
708 }
_vec_op_changed(int p_op,int p_id)709 void ShaderGraphView::_vec_op_changed(int p_op, int p_id) {
710
711 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
712 ur->create_action(TTR("Change Vec Operator"));
713 ur->add_do_method(graph.ptr(), "vec_op_node_set_op", type, p_id, p_op);
714 ur->add_undo_method(graph.ptr(), "vec_op_node_set_op", type, p_id, graph->vec_op_node_get_op(type, p_id));
715 ur->add_do_method(this, "_update_graph");
716 ur->add_undo_method(this, "_update_graph");
717 block_update = true;
718 ur->commit_action();
719 block_update = false;
720 }
_vec_scalar_op_changed(int p_op,int p_id)721 void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id) {
722
723 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
724 ur->create_action(TTR("Change Vec Scalar Operator"));
725 ur->add_do_method(graph.ptr(), "vec_scalar_op_node_set_op", type, p_id, p_op);
726 ur->add_undo_method(graph.ptr(), "vec_scalar_op_node_set_op", type, p_id, graph->vec_scalar_op_node_get_op(type, p_id));
727 ur->add_do_method(this, "_update_graph");
728 ur->add_undo_method(this, "_update_graph");
729 block_update = true;
730 ur->commit_action();
731 block_update = false;
732 }
_rgb_op_changed(int p_op,int p_id)733 void ShaderGraphView::_rgb_op_changed(int p_op, int p_id) {
734
735 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
736 ur->create_action(TTR("Change RGB Operator"));
737 ur->add_do_method(graph.ptr(), "rgb_op_node_set_op", type, p_id, p_op);
738 ur->add_undo_method(graph.ptr(), "rgb_op_node_set_op", type, p_id, graph->rgb_op_node_get_op(type, p_id));
739 ur->add_do_method(this, "_update_graph");
740 ur->add_undo_method(this, "_update_graph");
741 block_update = true;
742 ur->commit_action();
743 block_update = false;
744 }
_xform_inv_rev_changed(bool p_enabled,int p_id)745 void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id) {
746
747 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
748 ur->create_action(TTR("Toggle Rot Only"));
749 ur->add_do_method(graph.ptr(), "xform_vec_mult_node_set_no_translation", type, p_id, p_enabled);
750 ur->add_undo_method(graph.ptr(), "xform_vec_mult_node_set_no_translation", type, p_id, graph->xform_vec_mult_node_get_no_translation(type, p_id));
751 ur->add_do_method(this, "_update_graph");
752 ur->add_undo_method(this, "_update_graph");
753 block_update = true;
754 ur->commit_action();
755 block_update = false;
756 }
_scalar_func_changed(int p_func,int p_id)757 void ShaderGraphView::_scalar_func_changed(int p_func, int p_id) {
758
759 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
760 ur->create_action(TTR("Change Scalar Function"));
761 ur->add_do_method(graph.ptr(), "scalar_func_node_set_function", type, p_id, p_func);
762 ur->add_undo_method(graph.ptr(), "scalar_func_node_set_function", type, p_id, graph->scalar_func_node_get_function(type, p_id));
763 ur->add_do_method(this, "_update_graph");
764 ur->add_undo_method(this, "_update_graph");
765 block_update = true;
766 ur->commit_action();
767 block_update = false;
768 }
_vec_func_changed(int p_func,int p_id)769 void ShaderGraphView::_vec_func_changed(int p_func, int p_id) {
770
771 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
772 ur->create_action(TTR("Change Vec Function"));
773 ur->add_do_method(graph.ptr(), "vec_func_node_set_function", type, p_id, p_func);
774 ur->add_undo_method(graph.ptr(), "vec_func_node_set_function", type, p_id, graph->vec_func_node_get_function(type, p_id));
775 ur->add_do_method(this, "_update_graph");
776 ur->add_undo_method(this, "_update_graph");
777 block_update = true;
778 ur->commit_action();
779 block_update = false;
780 }
_scalar_input_changed(double p_value,int p_id)781 void ShaderGraphView::_scalar_input_changed(double p_value, int p_id) {
782
783 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
784 ur->create_action(TTR("Change Scalar Uniform"), UndoRedo::MERGE_ENDS);
785 ur->add_do_method(graph.ptr(), "scalar_input_node_set_value", type, p_id, p_value);
786 ur->add_undo_method(graph.ptr(), "scalar_input_node_set_value", type, p_id, graph->scalar_input_node_get_value(type, p_id));
787 ur->add_do_method(this, "_update_graph");
788 ur->add_undo_method(this, "_update_graph");
789 block_update = true;
790 ur->commit_action();
791 block_update = false;
792 }
_vec_input_changed(double p_value,int p_id,Array p_arr)793 void ShaderGraphView::_vec_input_changed(double p_value, int p_id, Array p_arr) {
794
795 Vector3 val;
796 for (int i = 0; i < p_arr.size(); i++) {
797 val[i] = p_arr[i].call("get_val");
798 }
799
800 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
801 ur->create_action(TTR("Change Vec Uniform"), UndoRedo::MERGE_ENDS);
802 ur->add_do_method(graph.ptr(), "vec_input_node_set_value", type, p_id, val);
803 ur->add_undo_method(graph.ptr(), "vec_input_node_set_value", type, p_id, graph->vec_input_node_get_value(type, p_id));
804 ur->add_do_method(this, "_update_graph");
805 ur->add_undo_method(this, "_update_graph");
806 block_update = true;
807 ur->commit_action();
808 block_update = false;
809 }
_xform_input_changed(int p_id,Node * p_button)810 void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button) {
811
812 ToolButton *tb = p_button->cast_to<ToolButton>();
813 ped_popup->set_pos(tb->get_global_pos() + Vector2(0, tb->get_size().height));
814 ped_popup->set_size(tb->get_size());
815 edited_id = p_id;
816 edited_def = -1;
817 ped_popup->edit(NULL, "", Variant::TRANSFORM, graph->xform_input_node_get_value(type, p_id), PROPERTY_HINT_NONE, "");
818 ped_popup->popup();
819 }
_xform_const_changed(int p_id,Node * p_button)820 void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button) {
821
822 ToolButton *tb = p_button->cast_to<ToolButton>();
823 ped_popup->set_pos(tb->get_global_pos() + Vector2(0, tb->get_size().height));
824 ped_popup->set_size(tb->get_size());
825 edited_id = p_id;
826 edited_def = -1;
827 ped_popup->edit(NULL, "", Variant::TRANSFORM, graph->xform_const_node_get_value(type, p_id), PROPERTY_HINT_NONE, "");
828 ped_popup->popup();
829 }
830
_rgb_input_changed(const Color & p_color,int p_id)831 void ShaderGraphView::_rgb_input_changed(const Color &p_color, int p_id) {
832
833 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
834 ur->create_action(TTR("Change RGB Uniform"), UndoRedo::MERGE_ENDS);
835 ur->add_do_method(graph.ptr(), "rgb_input_node_set_value", type, p_id, p_color);
836 ur->add_undo_method(graph.ptr(), "rgb_input_node_set_value", type, p_id, graph->rgb_input_node_get_value(type, p_id));
837 ur->add_do_method(this, "_update_graph");
838 ur->add_undo_method(this, "_update_graph");
839 block_update = true;
840 ur->commit_action();
841 block_update = false;
842 }
_tex_input_change(int p_id,Node * p_button)843 void ShaderGraphView::_tex_input_change(int p_id, Node *p_button) {
844 }
_cube_input_change(int p_id)845 void ShaderGraphView::_cube_input_change(int p_id) {
846 }
847
_variant_edited()848 void ShaderGraphView::_variant_edited() {
849
850 if (edited_def != -1) {
851
852 Variant v = ped_popup->get_variant();
853 Variant v2 = graph->default_get_value(type, edited_id, edited_def);
854 if (v2.get_type() == Variant::NIL)
855 switch (v.get_type()) {
856 case Variant::VECTOR3:
857 v2 = Vector3();
858 break;
859 case Variant::REAL:
860 v2 = 0.0;
861 break;
862 case Variant::TRANSFORM:
863 v2 = Transform();
864 break;
865 case Variant::COLOR:
866 v2 = Color();
867 break;
868 }
869 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
870 ur->create_action(TTR("Change Default Value"));
871 ur->add_do_method(graph.ptr(), "default_set_value", type, edited_id, edited_def, v);
872 ur->add_undo_method(graph.ptr(), "default_set_value", type, edited_id, edited_def, v2);
873 ur->add_do_method(this, "_update_graph");
874 ur->add_undo_method(this, "_update_graph");
875 ur->commit_action();
876 return;
877 }
878
879 if (graph->node_get_type(type, edited_id) == ShaderGraph::NODE_XFORM_CONST) {
880
881 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
882 ur->create_action(TTR("Change XForm Uniform"));
883 ur->add_do_method(graph.ptr(), "xform_const_node_set_value", type, edited_id, ped_popup->get_variant());
884 ur->add_undo_method(graph.ptr(), "xform_const_node_set_value", type, edited_id, graph->xform_const_node_get_value(type, edited_id));
885 ur->add_do_method(this, "_update_graph");
886 ur->add_undo_method(this, "_update_graph");
887 ur->commit_action();
888 }
889
890 if (graph->node_get_type(type, edited_id) == ShaderGraph::NODE_XFORM_INPUT) {
891
892 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
893 ur->create_action(TTR("Change XForm Uniform"));
894 ur->add_do_method(graph.ptr(), "xform_input_node_set_value", type, edited_id, ped_popup->get_variant());
895 ur->add_undo_method(graph.ptr(), "xform_input_node_set_value", type, edited_id, graph->xform_input_node_get_value(type, edited_id));
896 ur->add_do_method(this, "_update_graph");
897 ur->add_undo_method(this, "_update_graph");
898 ur->commit_action();
899 }
900
901 if (graph->node_get_type(type, edited_id) == ShaderGraph::NODE_TEXTURE_INPUT) {
902
903 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
904 ur->create_action(TTR("Change Texture Uniform"));
905 ur->add_do_method(graph.ptr(), "texture_input_node_set_value", type, edited_id, ped_popup->get_variant());
906 ur->add_undo_method(graph.ptr(), "texture_input_node_set_value", type, edited_id, graph->texture_input_node_get_value(type, edited_id));
907 ur->add_do_method(this, "_update_graph");
908 ur->add_undo_method(this, "_update_graph");
909 ur->commit_action();
910 }
911
912 if (graph->node_get_type(type, edited_id) == ShaderGraph::NODE_CUBEMAP_INPUT) {
913
914 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
915 ur->create_action(TTR("Change Cubemap Uniform"));
916 ur->add_do_method(graph.ptr(), "cubemap_input_node_set_value", type, edited_id, ped_popup->get_variant());
917 ur->add_undo_method(graph.ptr(), "cubemap_input_node_set_value", type, edited_id, graph->cubemap_input_node_get_value(type, edited_id));
918 ur->add_do_method(this, "_update_graph");
919 ur->add_undo_method(this, "_update_graph");
920 ur->commit_action();
921 }
922 }
923
_comment_edited(int p_id,Node * p_button)924 void ShaderGraphView::_comment_edited(int p_id, Node *p_button) {
925
926 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
927 TextEdit *te = p_button->cast_to<TextEdit>();
928 ur->create_action(TTR("Change Comment"), UndoRedo::MERGE_ENDS);
929 ur->add_do_method(graph.ptr(), "comment_node_set_text", type, p_id, te->get_text());
930 ur->add_undo_method(graph.ptr(), "comment_node_set_text", type, p_id, graph->comment_node_get_text(type, p_id));
931 ur->add_do_method(this, "_update_graph");
932 ur->add_undo_method(this, "_update_graph");
933 block_update = true;
934 ur->commit_action();
935 block_update = false;
936 }
937
_color_ramp_changed(int p_id,Node * p_ramp)938 void ShaderGraphView::_color_ramp_changed(int p_id, Node *p_ramp) {
939
940 GraphColorRampEdit *cr = p_ramp->cast_to<GraphColorRampEdit>();
941
942 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
943
944 Vector<float> offsets = cr->get_offsets();
945 Vector<Color> colors = cr->get_colors();
946
947 DVector<float> new_offsets;
948 DVector<Color> new_colors;
949 {
950 new_offsets.resize(offsets.size());
951 new_colors.resize(colors.size());
952 DVector<float>::Write ow = new_offsets.write();
953 DVector<Color>::Write cw = new_colors.write();
954 for (int i = 0; i < new_offsets.size(); i++) {
955 ow[i] = offsets[i];
956 cw[i] = colors[i];
957 }
958 }
959
960 DVector<float> old_offsets = graph->color_ramp_node_get_offsets(type, p_id);
961 DVector<Color> old_colors = graph->color_ramp_node_get_colors(type, p_id);
962
963 if (old_offsets.size() != new_offsets.size())
964 ur->create_action(TTR("Add/Remove to Color Ramp"));
965 else
966 ur->create_action(TTR("Modify Color Ramp"), UndoRedo::MERGE_ENDS);
967
968 ur->add_do_method(graph.ptr(), "color_ramp_node_set_ramp", type, p_id, new_colors, new_offsets);
969 ur->add_undo_method(graph.ptr(), "color_ramp_node_set_ramp", type, p_id, old_colors, old_offsets);
970 ur->add_do_method(this, "_update_graph");
971 ur->add_undo_method(this, "_update_graph");
972 block_update = true;
973 ur->commit_action();
974 block_update = false;
975 }
976
_curve_changed(int p_id,Node * p_curve)977 void ShaderGraphView::_curve_changed(int p_id, Node *p_curve) {
978
979 GraphCurveMapEdit *cr = p_curve->cast_to<GraphCurveMapEdit>();
980
981 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
982
983 Vector<Point2> points = cr->get_points();
984
985 DVector<Vector2> new_points;
986 {
987 new_points.resize(points.size());
988 DVector<Vector2>::Write ow = new_points.write();
989 for (int i = 0; i < new_points.size(); i++) {
990 ow[i] = points[i];
991 }
992 }
993
994 DVector<Vector2> old_points = graph->curve_map_node_get_points(type, p_id);
995
996 if (old_points.size() != new_points.size())
997 ur->create_action(TTR("Add/Remove to Curve Map"));
998 else
999 ur->create_action(TTR("Modify Curve Map"), UndoRedo::MERGE_ENDS);
1000
1001 ur->add_do_method(graph.ptr(), "curve_map_node_set_points", type, p_id, new_points);
1002 ur->add_undo_method(graph.ptr(), "curve_map_node_set_points", type, p_id, old_points);
1003 ur->add_do_method(this, "_update_graph");
1004 ur->add_undo_method(this, "_update_graph");
1005 block_update = true;
1006 ur->commit_action();
1007 block_update = false;
1008 }
1009
_input_name_changed(const String & p_name,int p_id,Node * p_line_edit)1010 void ShaderGraphView::_input_name_changed(const String &p_name, int p_id, Node *p_line_edit) {
1011
1012 LineEdit *le = p_line_edit->cast_to<LineEdit>();
1013 ERR_FAIL_COND(!le);
1014
1015 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1016 ur->create_action(TTR("Change Input Name"));
1017 ur->add_do_method(graph.ptr(), "input_node_set_name", type, p_id, p_name);
1018 ur->add_undo_method(graph.ptr(), "input_node_set_name", type, p_id, graph->input_node_get_name(type, p_id));
1019 ur->add_do_method(this, "_update_graph");
1020 ur->add_undo_method(this, "_update_graph");
1021 block_update = true;
1022 ur->commit_action();
1023 block_update = false;
1024 le->set_text(graph->input_node_get_name(type, p_id));
1025 }
1026
_tex_edited(int p_id,Node * p_button)1027 void ShaderGraphView::_tex_edited(int p_id, Node *p_button) {
1028
1029 ToolButton *tb = p_button->cast_to<ToolButton>();
1030 ped_popup->set_pos(tb->get_global_pos() + Vector2(0, tb->get_size().height));
1031 ped_popup->set_size(tb->get_size());
1032 edited_id = p_id;
1033 edited_def = -1;
1034 ped_popup->edit(NULL, "", Variant::OBJECT, graph->texture_input_node_get_value(type, p_id), PROPERTY_HINT_RESOURCE_TYPE, "Texture");
1035 }
1036
_cube_edited(int p_id,Node * p_button)1037 void ShaderGraphView::_cube_edited(int p_id, Node *p_button) {
1038
1039 ToolButton *tb = p_button->cast_to<ToolButton>();
1040 ped_popup->set_pos(tb->get_global_pos() + Vector2(0, tb->get_size().height));
1041 ped_popup->set_size(tb->get_size());
1042 edited_id = p_id;
1043 edited_def = -1;
1044 ped_popup->edit(NULL, "", Variant::OBJECT, graph->cubemap_input_node_get_value(type, p_id), PROPERTY_HINT_RESOURCE_TYPE, "CubeMap");
1045 }
1046
1047 //////////////view/////////////
1048
_connection_request(const String & p_from,int p_from_slot,const String & p_to,int p_to_slot)1049 void ShaderGraphView::_connection_request(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) {
1050
1051 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1052
1053 int from_idx = -1;
1054 int to_idx = -1;
1055 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next()) {
1056
1057 if (p_from == E->get()->get_name())
1058 from_idx = E->key();
1059 if (p_to == E->get()->get_name())
1060 to_idx = E->key();
1061 }
1062
1063 ERR_FAIL_COND(from_idx == -1);
1064 ERR_FAIL_COND(to_idx == -1);
1065
1066 ur->create_action(TTR("Connect Graph Nodes"));
1067
1068 List<ShaderGraph::Connection> conns;
1069
1070 graph->get_node_connections(type, &conns);
1071 //disconnect/reconnect dependencies
1072 ur->add_undo_method(graph.ptr(), "disconnect_node", type, from_idx, p_from_slot, to_idx, p_to_slot);
1073 for (List<ShaderGraph::Connection>::Element *E = conns.front(); E; E = E->next()) {
1074
1075 if (E->get().dst_id == to_idx && E->get().dst_slot == p_to_slot) {
1076 ur->add_do_method(graph.ptr(), "disconnect_node", type, E->get().src_id, E->get().src_slot, E->get().dst_id, E->get().dst_slot);
1077 ur->add_undo_method(graph.ptr(), "connect_node", type, E->get().src_id, E->get().src_slot, E->get().dst_id, E->get().dst_slot);
1078 }
1079 }
1080 ur->add_do_method(graph.ptr(), "connect_node", type, from_idx, p_from_slot, to_idx, p_to_slot);
1081 ur->add_do_method(this, "_update_graph");
1082 ur->add_undo_method(this, "_update_graph");
1083 ur->commit_action();
1084 }
1085
_disconnection_request(const String & p_from,int p_from_slot,const String & p_to,int p_to_slot)1086 void ShaderGraphView::_disconnection_request(const String &p_from, int p_from_slot, const String &p_to, int p_to_slot) {
1087
1088 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1089
1090 int from_idx = -1;
1091 int to_idx = -1;
1092 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next()) {
1093
1094 if (p_from == E->get()->get_name())
1095 from_idx = E->key();
1096 if (p_to == E->get()->get_name())
1097 to_idx = E->key();
1098 }
1099
1100 ERR_FAIL_COND(from_idx == -1);
1101 ERR_FAIL_COND(to_idx == -1);
1102
1103 if (!graph->is_node_connected(type, from_idx, p_from_slot, to_idx, p_to_slot))
1104 return; //nothing to disconnect
1105
1106 ur->create_action(TTR("Disconnect Graph Nodes"));
1107
1108 List<ShaderGraph::Connection> conns;
1109
1110 graph->get_node_connections(type, &conns);
1111 //disconnect/reconnect dependencies
1112 ur->add_do_method(graph.ptr(), "disconnect_node", type, from_idx, p_from_slot, to_idx, p_to_slot);
1113 ur->add_undo_method(graph.ptr(), "connect_node", type, from_idx, p_from_slot, to_idx, p_to_slot);
1114 ur->add_do_method(this, "_update_graph");
1115 ur->add_undo_method(this, "_update_graph");
1116 ur->commit_action();
1117 }
1118
_node_removed(int p_id)1119 void ShaderGraphView::_node_removed(int p_id) {
1120
1121 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1122 ur->create_action(TTR("Remove Shader Graph Node"));
1123
1124 ur->add_do_method(graph.ptr(), "node_remove", type, p_id);
1125 ur->add_undo_method(graph.ptr(), "node_add", type, graph->node_get_type(type, p_id), p_id);
1126 ur->add_undo_method(graph.ptr(), "node_set_state", type, p_id, graph->node_get_state(type, p_id));
1127 List<ShaderGraph::Connection> conns;
1128
1129 graph->get_node_connections(type, &conns);
1130 for (List<ShaderGraph::Connection>::Element *E = conns.front(); E; E = E->next()) {
1131
1132 if (E->get().dst_id == p_id || E->get().src_id == p_id) {
1133 ur->add_undo_method(graph.ptr(), "connect_node", type, E->get().src_id, E->get().src_slot, E->get().dst_id, E->get().dst_slot);
1134 }
1135 }
1136 ur->add_do_method(this, "_update_graph");
1137 ur->add_undo_method(this, "_update_graph");
1138 ur->commit_action();
1139 }
1140
_begin_node_move()1141 void ShaderGraphView::_begin_node_move() {
1142 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1143 ur->create_action(TTR("Move Shader Graph Node"));
1144 }
1145
_node_moved(const Vector2 & p_from,const Vector2 & p_to,int p_id)1146 void ShaderGraphView::_node_moved(const Vector2 &p_from, const Vector2 &p_to, int p_id) {
1147
1148 ERR_FAIL_COND(!node_map.has(p_id));
1149 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1150 ur->add_do_method(this, "_move_node", p_id, p_to);
1151 ur->add_undo_method(this, "_move_node", p_id, p_from);
1152 }
1153
_end_node_move()1154 void ShaderGraphView::_end_node_move() {
1155 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1156 ur->commit_action();
1157 }
1158
_move_node(int p_id,const Vector2 & p_to)1159 void ShaderGraphView::_move_node(int p_id, const Vector2 &p_to) {
1160
1161 ERR_FAIL_COND(!node_map.has(p_id));
1162 node_map[p_id]->set_offset(p_to);
1163 graph->node_set_pos(type, p_id, p_to);
1164 }
1165
_duplicate_nodes_request()1166 void ShaderGraphView::_duplicate_nodes_request() {
1167 Array s_id;
1168
1169 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next()) {
1170 ShaderGraph::NodeType t = graph->node_get_type(type, E->key());
1171 if (t == ShaderGraph::NODE_OUTPUT || t == ShaderGraph::NODE_INPUT)
1172 continue;
1173 GraphNode *gn = E->get();
1174 if (gn && gn->is_selected())
1175 s_id.push_back(E->key());
1176 }
1177
1178 if (s_id.size() == 0)
1179 return;
1180
1181 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1182 ur->create_action(TTR("Duplicate Graph Node(s)"));
1183 ur->add_do_method(this, "_duplicate_nodes", s_id);
1184 List<int> n_ids = graph->generate_ids(type, s_id.size());
1185 for (List<int>::Element *E = n_ids.front(); E; E = E->next())
1186 ur->add_undo_method(graph.ptr(), "node_remove", type, E->get());
1187 ur->add_do_method(this, "_update_graph");
1188 ur->add_undo_method(this, "_update_graph");
1189 ur->commit_action();
1190 }
1191
_duplicate_nodes(const Array & p_nodes)1192 void ShaderGraphView::_duplicate_nodes(const Array &p_nodes) {
1193 List<int> n = List<int>();
1194 for (int i = 0; i < p_nodes.size(); i++)
1195 n.push_back(p_nodes.get(i));
1196 graph->duplicate_nodes(type, n);
1197 call_deferred("_update_graph");
1198 }
1199
_delete_nodes_request()1200 void ShaderGraphView::_delete_nodes_request() {
1201 List<int> s_id = List<int>();
1202
1203 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next()) {
1204 ShaderGraph::NodeType t = graph->node_get_type(type, E->key());
1205 if (t == ShaderGraph::NODE_OUTPUT)
1206 continue;
1207 GraphNode *gn = E->get();
1208 if (gn && gn->is_selected())
1209 s_id.push_back(E->key());
1210 }
1211
1212 if (s_id.size() == 0)
1213 return;
1214
1215 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
1216 ur->create_action(TTR("Delete Shader Graph Node(s)"));
1217
1218 for (List<int>::Element *N = s_id.front(); N; N = N->next()) {
1219 ur->add_do_method(graph.ptr(), "node_remove", type, N->get());
1220 ur->add_undo_method(graph.ptr(), "node_add", type, graph->node_get_type(type, N->get()), N->get());
1221 ur->add_undo_method(graph.ptr(), "node_set_state", type, N->get(), graph->node_get_state(type, N->get()));
1222 List<ShaderGraph::Connection> conns;
1223
1224 graph->get_node_connections(type, &conns);
1225 for (List<ShaderGraph::Connection>::Element *E = conns.front(); E; E = E->next()) {
1226
1227 if (E->get().dst_id == N->get() || E->get().src_id == N->get()) {
1228 ur->add_undo_method(graph.ptr(), "connect_node", type, E->get().src_id, E->get().src_slot, E->get().dst_id, E->get().dst_slot);
1229 }
1230 }
1231 }
1232 ur->add_do_method(this, "_update_graph");
1233 ur->add_undo_method(this, "_update_graph");
1234 ur->commit_action();
1235 }
1236
_default_changed(int p_id,Node * p_button,int p_param,int v_type,String p_hint)1237 void ShaderGraphView::_default_changed(int p_id, Node *p_button, int p_param, int v_type, String p_hint) {
1238 ToolButton *tb = p_button->cast_to<ToolButton>();
1239 ped_popup->set_pos(tb->get_global_pos() + Vector2(0, tb->get_size().height));
1240 ped_popup->set_size(tb->get_size());
1241 edited_id = p_id;
1242 edited_def = p_param;
1243 Variant::Type vt = (Variant::Type)v_type;
1244 Variant v = graph->default_get_value(type, p_id, edited_def);
1245 int h = PROPERTY_HINT_NONE;
1246 if (v.get_type() == Variant::NIL)
1247 switch (vt) {
1248 case Variant::VECTOR3:
1249 v = Vector3();
1250 break;
1251 case Variant::REAL:
1252 h = PROPERTY_HINT_RANGE;
1253 v = 0.0;
1254 break;
1255 case Variant::TRANSFORM:
1256 v = Transform();
1257 break;
1258 case Variant::COLOR:
1259 h = PROPERTY_HINT_COLOR_NO_ALPHA;
1260 v = Color();
1261 break;
1262 }
1263
1264 ped_popup->edit(NULL, "", vt, v, h, p_hint);
1265
1266 ped_popup->popup();
1267 }
1268
make_label(String text,Variant::Type v_type)1269 ToolButton *ShaderGraphView::make_label(String text, Variant::Type v_type) {
1270 ToolButton *l = memnew(ToolButton);
1271 l->set_text(text);
1272 l->set_text_align(ToolButton::ALIGN_LEFT);
1273 l->add_style_override("hover", l->get_stylebox("normal", "ToolButton"));
1274 l->add_style_override("pressed", l->get_stylebox("normal", "ToolButton"));
1275 l->add_style_override("focus", l->get_stylebox("normal", "ToolButton"));
1276 switch (v_type) {
1277 case Variant::REAL:
1278 l->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
1279 break;
1280 case Variant::VECTOR3:
1281 l->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
1282 break;
1283 case Variant::TRANSFORM:
1284 l->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
1285 break;
1286 case Variant::COLOR:
1287 l->set_icon(ped_popup->get_icon("Color", "EditorIcons"));
1288 }
1289 return l;
1290 }
1291
make_editor(String text,GraphNode * gn,int p_id,int param,Variant::Type v_type,String p_hint)1292 ToolButton *ShaderGraphView::make_editor(String text, GraphNode *gn, int p_id, int param, Variant::Type v_type, String p_hint) {
1293 ToolButton *edit = memnew(ToolButton);
1294 edit->set_text(text);
1295 edit->set_text_align(ToolButton::ALIGN_LEFT);
1296 edit->set_flat(false);
1297 edit->add_style_override("normal", gn->get_stylebox("defaultframe", "GraphNode"));
1298 edit->add_style_override("hover", gn->get_stylebox("defaultframe", "GraphNode"));
1299 edit->add_style_override("pressed", gn->get_stylebox("defaultframe", "GraphNode"));
1300 edit->add_style_override("focus", gn->get_stylebox("defaultfocus", "GraphNode"));
1301 edit->connect("pressed", this, "_default_changed", varray(p_id, edit, param, v_type, p_hint));
1302
1303 switch (v_type) {
1304 case Variant::REAL:
1305 edit->set_icon(ped_popup->get_icon("Real", "EditorIcons"));
1306 break;
1307 case Variant::VECTOR3:
1308 edit->set_icon(ped_popup->get_icon("Vector", "EditorIcons"));
1309 break;
1310 case Variant::TRANSFORM:
1311 edit->set_icon(ped_popup->get_icon("Matrix", "EditorIcons"));
1312 break;
1313 case Variant::COLOR:
1314 Image icon_color = Image(15, 15, false, Image::FORMAT_RGB);
1315 Color c = graph->default_get_value(type, p_id, param);
1316 for (int x = 1; x < 14; x++)
1317 for (int y = 1; y < 14; y++)
1318 icon_color.put_pixel(x, y, c);
1319 Ref<ImageTexture> t;
1320 t.instance();
1321 t->create_from_image(icon_color);
1322 edit->set_icon(t);
1323 break;
1324 }
1325 return edit;
1326 }
1327
_create_node(int p_id)1328 void ShaderGraphView::_create_node(int p_id) {
1329
1330 GraphNode *gn = memnew(GraphNode);
1331 gn->set_show_close_button(true);
1332 Color typecol[4] = {
1333 Color(0.9, 0.4, 1),
1334 Color(0.8, 1, 0.2),
1335 Color(1, 0.2, 0.2),
1336 Color(0, 1, 1)
1337 };
1338
1339 const String hint_spin = "-65536,65535,0.001";
1340 const String hint_slider = "0.0,1.0,0.01,slider";
1341
1342 switch (graph->node_get_type(type, p_id)) {
1343
1344 case ShaderGraph::NODE_INPUT: {
1345
1346 gn->set_title("Input");
1347
1348 List<ShaderGraph::SlotInfo> si;
1349 ShaderGraph::get_input_output_node_slot_info(graph->get_mode(), type, &si);
1350
1351 int idx = 0;
1352 for (List<ShaderGraph::SlotInfo>::Element *E = si.front(); E; E = E->next()) {
1353 ShaderGraph::SlotInfo &s = E->get();
1354 if (s.dir == ShaderGraph::SLOT_IN) {
1355
1356 Label *l = memnew(Label);
1357 l->set_text(s.name);
1358 l->set_align(Label::ALIGN_RIGHT);
1359 gn->add_child(l);
1360 gn->set_slot(idx, false, 0, Color(), true, s.type, typecol[s.type]);
1361 idx++;
1362 }
1363 }
1364
1365 } break; // all inputs (case Shader type dependent)
1366 case ShaderGraph::NODE_SCALAR_CONST: {
1367 gn->set_title("Scalar");
1368 SpinBox *sb = memnew(SpinBox);
1369 sb->set_min(-100000);
1370 sb->set_max(100000);
1371 sb->set_step(0.001);
1372 sb->set_val(graph->scalar_const_node_get_value(type, p_id));
1373 sb->connect("value_changed", this, "_scalar_const_changed", varray(p_id));
1374 gn->add_child(sb);
1375 gn->set_slot(0, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1376
1377 } break; //scalar constant
1378 case ShaderGraph::NODE_VEC_CONST: {
1379
1380 gn->set_title("Vector");
1381 Array v3p(true);
1382 for (int i = 0; i < 3; i++) {
1383 HBoxContainer *hbc = memnew(HBoxContainer);
1384 Label *l = memnew(Label);
1385 l->set_text(String::chr('X' + i));
1386 hbc->add_child(l);
1387 SpinBox *sb = memnew(SpinBox);
1388 sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1389 sb->set_min(-100000);
1390 sb->set_max(100000);
1391 sb->set_step(0.001);
1392 sb->set_val(graph->vec_const_node_get_value(type, p_id)[i]);
1393 sb->connect("value_changed", this, "_vec_const_changed", varray(p_id, v3p));
1394 v3p.push_back(sb);
1395 hbc->add_child(sb);
1396 gn->add_child(hbc);
1397 }
1398 gn->set_slot(0, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1399
1400 } break; //vec3 constant
1401 case ShaderGraph::NODE_RGB_CONST: {
1402
1403 gn->set_title("Color");
1404 ColorPickerButton *cpb = memnew(ColorPickerButton);
1405 cpb->set_color(graph->rgb_const_node_get_value(type, p_id));
1406 cpb->connect("color_changed", this, "_rgb_const_changed", varray(p_id));
1407 gn->add_child(cpb);
1408 Label *l = memnew(Label);
1409 l->set_text("RGB");
1410 l->set_align(Label::ALIGN_RIGHT);
1411 gn->add_child(l);
1412 l = memnew(Label);
1413 l->set_text("Alpha");
1414 l->set_align(Label::ALIGN_RIGHT);
1415 gn->add_child(l);
1416
1417 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1418 gn->set_slot(2, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1419
1420 } break; //rgb constant (shows a color picker instead)
1421 case ShaderGraph::NODE_XFORM_CONST: {
1422 gn->set_title("XForm");
1423 ToolButton *edit = memnew(ToolButton);
1424 edit->set_text("edit..");
1425 edit->connect("pressed", this, "_xform_const_changed", varray(p_id, edit));
1426 gn->add_child(edit);
1427 gn->set_slot(0, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM]);
1428
1429 } break; // 4x4 matrix constant
1430 case ShaderGraph::NODE_TIME: {
1431
1432 gn->set_title("Time");
1433 Label *l = memnew(Label);
1434 l->set_text("(s)");
1435 l->set_align(Label::ALIGN_RIGHT);
1436 gn->add_child(l);
1437 gn->set_slot(0, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1438
1439 } break; // time in seconds
1440 case ShaderGraph::NODE_SCREEN_TEX: {
1441
1442 gn->set_title("ScreenTex");
1443 HBoxContainer *hbc = memnew(HBoxContainer);
1444 hbc->add_constant_override("separation", 0);
1445 if (!graph->is_slot_connected(type, p_id, 0)) {
1446 Vector3 v = graph->default_get_value(type, p_id, 0);
1447 hbc->add_child(make_editor("UV: " + v, gn, p_id, 0, Variant::VECTOR3));
1448 } else {
1449 hbc->add_child(make_label("UV", Variant::VECTOR3));
1450 }
1451 hbc->add_spacer();
1452 hbc->add_child(memnew(Label("RGB")));
1453 gn->add_child(hbc);
1454 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1455
1456 } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
1457 case ShaderGraph::NODE_SCALAR_OP: {
1458
1459 gn->set_title("ScalarOp");
1460 static const char *op_name[ShaderGraph::SCALAR_MAX_OP] = {
1461 ("Add"),
1462 ("Sub"),
1463 ("Mul"),
1464 ("Div"),
1465 ("Mod"),
1466 ("Pow"),
1467 ("Max"),
1468 ("Min"),
1469 ("Atan2")
1470 };
1471
1472 OptionButton *ob = memnew(OptionButton);
1473 for (int i = 0; i < ShaderGraph::SCALAR_MAX_OP; i++) {
1474
1475 ob->add_item(op_name[i], i);
1476 }
1477
1478 ob->select(graph->scalar_op_node_get_op(type, p_id));
1479 ob->connect("item_selected", this, "_scalar_op_changed", varray(p_id));
1480 gn->add_child(ob);
1481
1482 HBoxContainer *hbc = memnew(HBoxContainer);
1483 hbc->add_constant_override("separation", 0);
1484 if (graph->is_slot_connected(type, p_id, 0)) {
1485 hbc->add_child(make_label("a", Variant::REAL));
1486 } else {
1487 float v = graph->default_get_value(type, p_id, 0);
1488 hbc->add_child(make_editor(String("a: ") + Variant(v), gn, p_id, 0, Variant::REAL, hint_spin));
1489 }
1490 hbc->add_spacer();
1491 hbc->add_child(memnew(Label("out")));
1492 gn->add_child(hbc);
1493 if (graph->is_slot_connected(type, p_id, 1)) {
1494 gn->add_child(make_label("b", Variant::REAL));
1495 } else {
1496 float v = graph->default_get_value(type, p_id, 1);
1497 gn->add_child(make_editor(String("b: ") + Variant(v), gn, p_id, 1, Variant::REAL, hint_spin));
1498 }
1499
1500 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1501 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
1502
1503 } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
1504 case ShaderGraph::NODE_VEC_OP: {
1505
1506 gn->set_title("VecOp");
1507 static const char *op_name[ShaderGraph::VEC_MAX_OP] = {
1508 ("Add"),
1509 ("Sub"),
1510 ("Mul"),
1511 ("Div"),
1512 ("Mod"),
1513 ("Pow"),
1514 ("Max"),
1515 ("Min"),
1516 ("Cross")
1517 };
1518
1519 OptionButton *ob = memnew(OptionButton);
1520 for (int i = 0; i < ShaderGraph::VEC_MAX_OP; i++) {
1521
1522 ob->add_item(op_name[i], i);
1523 }
1524
1525 ob->select(graph->vec_op_node_get_op(type, p_id));
1526 ob->connect("item_selected", this, "_vec_op_changed", varray(p_id));
1527 gn->add_child(ob);
1528
1529 HBoxContainer *hbc = memnew(HBoxContainer);
1530 hbc->add_constant_override("separation", 0);
1531 if (graph->is_slot_connected(type, p_id, 0)) {
1532 hbc->add_child(make_label("a", Variant::VECTOR3));
1533 } else {
1534 Vector3 v = graph->default_get_value(type, p_id, 0);
1535 hbc->add_child(make_editor(String("a: ") + v, gn, p_id, 0, Variant::VECTOR3));
1536 }
1537 hbc->add_spacer();
1538 hbc->add_child(memnew(Label("out")));
1539 gn->add_child(hbc);
1540 if (graph->is_slot_connected(type, p_id, 1)) {
1541 gn->add_child(make_label("b", Variant::VECTOR3));
1542 } else {
1543 Vector3 v = graph->default_get_value(type, p_id, 1);
1544 gn->add_child(make_editor(String("b: ") + v, gn, p_id, 1, Variant::VECTOR3));
1545 }
1546
1547 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1548 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1549
1550 } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc)
1551 case ShaderGraph::NODE_VEC_SCALAR_OP: {
1552
1553 gn->set_title("VecScalarOp");
1554 static const char *op_name[ShaderGraph::VEC_SCALAR_MAX_OP] = {
1555 ("Mul"),
1556 ("Div"),
1557 ("Pow"),
1558 };
1559
1560 OptionButton *ob = memnew(OptionButton);
1561 for (int i = 0; i < ShaderGraph::VEC_SCALAR_MAX_OP; i++) {
1562
1563 ob->add_item(op_name[i], i);
1564 }
1565
1566 ob->select(graph->vec_scalar_op_node_get_op(type, p_id));
1567 ob->connect("item_selected", this, "_vec_scalar_op_changed", varray(p_id));
1568 gn->add_child(ob);
1569
1570 HBoxContainer *hbc = memnew(HBoxContainer);
1571 hbc->add_constant_override("separation", 0);
1572 if (graph->is_slot_connected(type, p_id, 0)) {
1573 hbc->add_child(make_label("a", Variant::VECTOR3));
1574 } else {
1575 Vector3 v = graph->default_get_value(type, p_id, 0);
1576 hbc->add_child(make_editor(String("a: ") + v, gn, p_id, 0, Variant::VECTOR3));
1577 }
1578 hbc->add_spacer();
1579 hbc->add_child(memnew(Label("out")));
1580 gn->add_child(hbc);
1581
1582 if (graph->is_slot_connected(type, p_id, 1)) {
1583 gn->add_child(make_label("b", Variant::REAL));
1584 } else {
1585 float v = graph->default_get_value(type, p_id, 1);
1586 gn->add_child(make_editor(String("b: ") + Variant(v), gn, p_id, 1, Variant::REAL, hint_spin));
1587 }
1588 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1589 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
1590
1591 } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
1592 case ShaderGraph::NODE_RGB_OP: {
1593
1594 gn->set_title("RGB Op");
1595 static const char *op_name[ShaderGraph::RGB_MAX_OP] = {
1596 ("Screen"),
1597 ("Difference"),
1598 ("Darken"),
1599 ("Lighten"),
1600 ("Overlay"),
1601 ("Dodge"),
1602 ("Burn"),
1603 ("SoftLight"),
1604 ("HardLight")
1605 };
1606
1607 OptionButton *ob = memnew(OptionButton);
1608 for (int i = 0; i < ShaderGraph::RGB_MAX_OP; i++) {
1609
1610 ob->add_item(op_name[i], i);
1611 }
1612
1613 ob->select(graph->rgb_op_node_get_op(type, p_id));
1614 ob->connect("item_selected", this, "_rgb_op_changed", varray(p_id));
1615 gn->add_child(ob);
1616
1617 HBoxContainer *hbc = memnew(HBoxContainer);
1618 hbc->add_constant_override("separation", 0);
1619 if (graph->is_slot_connected(type, p_id, 0)) {
1620 hbc->add_child(make_label("a", Variant::COLOR));
1621 } else {
1622 hbc->add_child(make_editor(String("a: "), gn, p_id, 0, Variant::COLOR));
1623 }
1624 hbc->add_spacer();
1625 hbc->add_child(memnew(Label("out")));
1626 gn->add_child(hbc);
1627 if (graph->is_slot_connected(type, p_id, 1)) {
1628 gn->add_child(make_label("b", Variant::COLOR));
1629 } else {
1630 gn->add_child(make_editor(String("b: "), gn, p_id, 1, Variant::COLOR));
1631 }
1632
1633 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1634 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1635
1636 } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc.
1637 case ShaderGraph::NODE_XFORM_MULT: {
1638
1639 gn->set_title("XFMult");
1640 HBoxContainer *hbc = memnew(HBoxContainer);
1641 if (graph->is_slot_connected(type, p_id, 0)) {
1642 hbc->add_child(make_label("a", Variant::TRANSFORM));
1643 } else {
1644 hbc->add_child(make_editor(String("a: edit..."), gn, p_id, 0, Variant::TRANSFORM));
1645 }
1646 hbc->add_spacer();
1647 hbc->add_child(memnew(Label("out")));
1648 gn->add_child(hbc);
1649 if (graph->is_slot_connected(type, p_id, 1)) {
1650 gn->add_child(make_label("b", Variant::TRANSFORM));
1651 } else {
1652 gn->add_child(make_editor(String("b: edit..."), gn, p_id, 1, Variant::TRANSFORM));
1653 }
1654
1655 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM], true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM]);
1656 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM], false, 0, Color());
1657
1658 } break; // mat4 x mat4
1659 case ShaderGraph::NODE_XFORM_VEC_MULT: {
1660
1661 gn->set_title("XFVecMult");
1662
1663 CheckBox *button = memnew(CheckBox("RotOnly"));
1664 button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type, p_id));
1665 button->connect("toggled", this, "_xform_inv_rev_changed", varray(p_id));
1666
1667 gn->add_child(button);
1668
1669 HBoxContainer *hbc = memnew(HBoxContainer);
1670 hbc->add_constant_override("separation", 0);
1671 if (graph->is_slot_connected(type, p_id, 0)) {
1672 hbc->add_child(make_label("xf", Variant::TRANSFORM));
1673 } else {
1674 hbc->add_child(make_editor(String("xf: edit..."), gn, p_id, 0, Variant::TRANSFORM));
1675 }
1676 hbc->add_spacer();
1677 Label *l = memnew(Label("out"));
1678 l->set_align(Label::ALIGN_RIGHT);
1679 hbc->add_child(l);
1680 gn->add_child(hbc);
1681 if (graph->is_slot_connected(type, p_id, 1)) {
1682 gn->add_child(make_label("a", Variant::VECTOR3));
1683 } else {
1684 Vector3 v = graph->default_get_value(type, p_id, 1);
1685 gn->add_child(make_editor(String("a: ") + v, gn, p_id, 1, Variant::VECTOR3));
1686 }
1687
1688 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1689 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1690
1691 } break;
1692 case ShaderGraph::NODE_XFORM_VEC_INV_MULT: {
1693
1694 gn->set_title("XFVecInvMult");
1695
1696 CheckBox *button = memnew(CheckBox("RotOnly"));
1697 button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type, p_id));
1698 button->connect("toggled", this, "_xform_inv_rev_changed", varray(p_id));
1699
1700 gn->add_child(button);
1701
1702 if (graph->is_slot_connected(type, p_id, 0)) {
1703 gn->add_child(make_label("a", Variant::VECTOR3));
1704 } else {
1705 Vector3 v = graph->default_get_value(type, p_id, 0);
1706 gn->add_child(make_editor(String("a: ") + v, gn, p_id, 0, Variant::VECTOR3));
1707 }
1708 HBoxContainer *hbc = memnew(HBoxContainer);
1709 hbc->add_constant_override("separation", 0);
1710 if (graph->is_slot_connected(type, p_id, 1)) {
1711 hbc->add_child(make_label("xf", Variant::TRANSFORM));
1712 } else {
1713 hbc->add_child(make_editor(String("xf: edit..."), gn, p_id, 1, Variant::TRANSFORM));
1714 }
1715 hbc->add_spacer();
1716 Label *l = memnew(Label("out"));
1717 l->set_align(Label::ALIGN_RIGHT);
1718 hbc->add_child(l);
1719 gn->add_child(hbc);
1720
1721 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1722 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1723
1724 } break; // mat4 x vec3 inverse mult (with no-translation option)
1725 case ShaderGraph::NODE_SCALAR_FUNC: {
1726
1727 gn->set_title("ScalarFunc");
1728 static const char *func_name[ShaderGraph::SCALAR_MAX_FUNC] = {
1729 ("Sin"),
1730 ("Cos"),
1731 ("Tan"),
1732 ("ASin"),
1733 ("ACos"),
1734 ("ATan"),
1735 ("SinH"),
1736 ("CosH"),
1737 ("TanH"),
1738 ("Log"),
1739 ("Exp"),
1740 ("Sqrt"),
1741 ("Abs"),
1742 ("Sign"),
1743 ("Floor"),
1744 ("Round"),
1745 ("Ceil"),
1746 ("Frac"),
1747 ("Satr"),
1748 ("Neg")
1749 };
1750
1751 OptionButton *ob = memnew(OptionButton);
1752 for (int i = 0; i < ShaderGraph::SCALAR_MAX_FUNC; i++) {
1753
1754 ob->add_item(func_name[i], i);
1755 }
1756
1757 ob->select(graph->scalar_func_node_get_function(type, p_id));
1758 ob->connect("item_selected", this, "_scalar_func_changed", varray(p_id));
1759 gn->add_child(ob);
1760
1761 HBoxContainer *hbc = memnew(HBoxContainer);
1762 if (graph->is_slot_connected(type, p_id, 0)) {
1763 hbc->add_child(make_label("in", Variant::REAL));
1764 } else {
1765 float v = graph->default_get_value(type, p_id, 0);
1766 hbc->add_child(make_editor(String("in: ") + Variant(v), gn, p_id, 0, Variant::REAL, hint_spin));
1767 }
1768 hbc->add_spacer();
1769 hbc->add_child(memnew(Label("out")));
1770 gn->add_child(hbc);
1771
1772 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1773
1774 } break; // scalar function (sin: { } break; cos: { } break; etc)
1775 case ShaderGraph::NODE_VEC_FUNC: {
1776
1777 gn->set_title("VecFunc");
1778 static const char *func_name[ShaderGraph::VEC_MAX_FUNC] = {
1779 ("Normalize"),
1780 ("Saturate"),
1781 ("Negate"),
1782 ("Reciprocal"),
1783 ("RGB to HSV"),
1784 ("HSV to RGB"),
1785 };
1786
1787 OptionButton *ob = memnew(OptionButton);
1788 for (int i = 0; i < ShaderGraph::VEC_MAX_FUNC; i++) {
1789
1790 ob->add_item(func_name[i], i);
1791 }
1792
1793 ob->select(graph->vec_func_node_get_function(type, p_id));
1794 ob->connect("item_selected", this, "_vec_func_changed", varray(p_id));
1795 gn->add_child(ob);
1796
1797 HBoxContainer *hbc = memnew(HBoxContainer);
1798 hbc->add_constant_override("separation", 0);
1799 if (graph->is_slot_connected(type, p_id, 0)) {
1800 hbc->add_child(make_label("in", Variant::VECTOR3));
1801 } else {
1802 Vector3 v = graph->default_get_value(type, p_id, 0);
1803 hbc->add_child(make_editor(String("in: ") + v, gn, p_id, 0, Variant::VECTOR3));
1804 }
1805 hbc->add_spacer();
1806 hbc->add_child(memnew(Label("out")));
1807 gn->add_child(hbc);
1808
1809 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1810
1811 } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc)
1812 case ShaderGraph::NODE_VEC_LEN: {
1813 gn->set_title("VecLength");
1814 HBoxContainer *hbc = memnew(HBoxContainer);
1815 if (graph->is_slot_connected(type, p_id, 0)) {
1816 hbc->add_child(make_label("in", Variant::VECTOR3));
1817 } else {
1818 Vector3 v = graph->default_get_value(type, p_id, 0);
1819 hbc->add_child(make_editor(String("in: ") + v, gn, p_id, 0, Variant::VECTOR3));
1820 }
1821 hbc->add_spacer();
1822 hbc->add_child(memnew(Label("len")));
1823 gn->add_child(hbc);
1824
1825 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1826
1827 } break; // vec3 length
1828 case ShaderGraph::NODE_DOT_PROD: {
1829
1830 gn->set_title("DotProduct");
1831 HBoxContainer *hbc = memnew(HBoxContainer);
1832 hbc->add_constant_override("separation", 0);
1833 if (graph->is_slot_connected(type, p_id, 0)) {
1834 hbc->add_child(make_label("a", Variant::VECTOR3));
1835 } else {
1836 Vector3 v = graph->default_get_value(type, p_id, 0);
1837 hbc->add_child(make_editor(String("a: ") + v, gn, p_id, 0, Variant::VECTOR3));
1838 }
1839 hbc->add_spacer();
1840 hbc->add_child(memnew(Label("dp")));
1841 gn->add_child(hbc);
1842 if (graph->is_slot_connected(type, p_id, 1)) {
1843 gn->add_child(make_label("b", Variant::VECTOR3));
1844 } else {
1845 Vector3 v = graph->default_get_value(type, p_id, 1);
1846 gn->add_child(make_editor(String("b: ") + v, gn, p_id, 1, Variant::VECTOR3));
1847 }
1848
1849 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1850 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1851
1852 } break; // vec3 . vec3 (dot product -> scalar output)
1853 case ShaderGraph::NODE_VEC_TO_SCALAR: {
1854
1855 gn->set_title("Vec2Scalar");
1856 HBoxContainer *hbc = memnew(HBoxContainer);
1857 hbc->add_constant_override("separation", 0);
1858 if (graph->is_slot_connected(type, p_id, 0)) {
1859 hbc->add_child(make_label("vec", Variant::VECTOR3));
1860 } else {
1861 Vector3 v = graph->default_get_value(type, p_id, 0);
1862 hbc->add_child(make_editor(String("vec: ") + v, gn, p_id, 0, Variant::VECTOR3));
1863 }
1864 hbc->add_spacer();
1865 Label *l = memnew(Label("x"));
1866 l->set_align(Label::ALIGN_RIGHT);
1867 hbc->add_child(l);
1868 gn->add_child(hbc);
1869 l = memnew(Label("y"));
1870 l->set_align(Label::ALIGN_RIGHT);
1871 gn->add_child(l);
1872 l = memnew(Label("z"));
1873 l->set_align(Label::ALIGN_RIGHT);
1874 gn->add_child(l);
1875
1876 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1877 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1878 gn->set_slot(2, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
1879
1880 } break; // 1 vec3 input: { } break; 3 scalar outputs
1881 case ShaderGraph::NODE_SCALAR_TO_VEC: {
1882
1883 gn->set_title("Scalar2Vec");
1884 HBoxContainer *hbc = memnew(HBoxContainer);
1885 if (graph->is_slot_connected(type, p_id, 0)) {
1886 hbc->add_child(make_label("x", Variant::REAL));
1887 } else {
1888 float v = graph->default_get_value(type, p_id, 0);
1889 hbc->add_child(make_editor(String("x: ") + Variant(v), gn, p_id, 0, Variant::REAL));
1890 }
1891 hbc->add_spacer();
1892 hbc->add_child(memnew(Label("vec")));
1893 gn->add_child(hbc);
1894 if (graph->is_slot_connected(type, p_id, 1)) {
1895 gn->add_child(make_label("y", Variant::REAL));
1896 } else {
1897 float v = graph->default_get_value(type, p_id, 1);
1898 gn->add_child(make_editor(String("y: ") + Variant(v), gn, p_id, 1, Variant::REAL));
1899 }
1900 if (graph->is_slot_connected(type, p_id, 2)) {
1901 gn->add_child(make_label("in", Variant::REAL));
1902 } else {
1903 float v = graph->default_get_value(type, p_id, 2);
1904 gn->add_child(make_editor(String("in: ") + Variant(v), gn, p_id, 2, Variant::REAL));
1905 }
1906
1907 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1908 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
1909 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
1910
1911 } break; // 3 scalar input: { } break; 1 vec3 output
1912 case ShaderGraph::NODE_VEC_TO_XFORM: {
1913
1914 gn->set_title("Vec2XForm");
1915 HBoxContainer *hbc = memnew(HBoxContainer);
1916 hbc->add_constant_override("separation", 0);
1917 if (graph->is_slot_connected(type, p_id, 0)) {
1918 hbc->add_child(make_label("x", Variant::VECTOR3));
1919 } else {
1920 Vector3 v = graph->default_get_value(type, p_id, 0);
1921 hbc->add_child(make_editor(String("x: ") + v, gn, p_id, 0, Variant::VECTOR3));
1922 }
1923 hbc->add_spacer();
1924 hbc->add_child(memnew(Label("xf")));
1925 gn->add_child(hbc);
1926 if (graph->is_slot_connected(type, p_id, 1)) {
1927 gn->add_child(make_label("y", Variant::VECTOR3));
1928 } else {
1929 Vector3 v = graph->default_get_value(type, p_id, 1);
1930 gn->add_child(make_editor(String("y: ") + v, gn, p_id, 1, Variant::VECTOR3));
1931 }
1932 if (graph->is_slot_connected(type, p_id, 2)) {
1933 gn->add_child(make_label("z", Variant::VECTOR3));
1934 } else {
1935 Vector3 v = graph->default_get_value(type, p_id, 2);
1936 gn->add_child(make_editor(String("z: ") + v, gn, p_id, 2, Variant::VECTOR3));
1937 }
1938 if (graph->is_slot_connected(type, p_id, 3)) {
1939 gn->add_child(make_label("ofs", Variant::VECTOR3));
1940 } else {
1941 Vector3 v = graph->default_get_value(type, p_id, 3);
1942 gn->add_child(make_editor(String("ofs: ") + v, gn, p_id, 3, Variant::VECTOR3));
1943 }
1944
1945 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM]);
1946 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1947 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1948 gn->set_slot(3, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
1949
1950 } break; // 3 vec input: { } break; 1 xform output
1951 case ShaderGraph::NODE_XFORM_TO_VEC: {
1952
1953 gn->set_title("XForm2Vec");
1954
1955 HBoxContainer *hbc = memnew(HBoxContainer);
1956 hbc->add_constant_override("separation", 0);
1957 if (graph->is_slot_connected(type, p_id, 0)) {
1958 hbc->add_child(make_label("fx", Variant::TRANSFORM));
1959 } else {
1960 hbc->add_child(make_editor(String("fx: edit..."), gn, p_id, 0, Variant::TRANSFORM));
1961 }
1962 hbc->add_spacer();
1963 Label *l = memnew(Label("x"));
1964 l->set_align(Label::ALIGN_RIGHT);
1965 hbc->add_child(l);
1966 gn->add_child(hbc);
1967 l = memnew(Label("y"));
1968 l->set_align(Label::ALIGN_RIGHT);
1969 gn->add_child(l);
1970 l = memnew(Label("z"));
1971 l->set_align(Label::ALIGN_RIGHT);
1972 gn->add_child(l);
1973 l = memnew(Label("ofs"));
1974 l->set_align(Label::ALIGN_RIGHT);
1975 gn->add_child(l);
1976
1977 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1978 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1979 gn->set_slot(2, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1980 gn->set_slot(3, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
1981
1982 } break; // 3 vec input: { } break; 1 xform output
1983 case ShaderGraph::NODE_SCALAR_INTERP: {
1984
1985 gn->set_title("ScalarInterp");
1986 HBoxContainer *hbc = memnew(HBoxContainer);
1987 hbc->add_constant_override("separation", 0);
1988 if (graph->is_slot_connected(type, p_id, 0)) {
1989 hbc->add_child(make_label("a", Variant::REAL));
1990 } else {
1991 float v = graph->default_get_value(type, p_id, 0);
1992 hbc->add_child(make_editor(String("a: ") + Variant(v), gn, p_id, 0, Variant::REAL, hint_spin));
1993 }
1994 hbc->add_spacer();
1995 hbc->add_child(memnew(Label("interp")));
1996 gn->add_child(hbc);
1997 if (graph->is_slot_connected(type, p_id, 1)) {
1998 gn->add_child(make_label("b", Variant::REAL));
1999 } else {
2000 float v = graph->default_get_value(type, p_id, 1);
2001 gn->add_child(make_editor(String("b: ") + Variant(v), gn, p_id, 1, Variant::REAL, hint_spin));
2002 }
2003 if (graph->is_slot_connected(type, p_id, 2)) {
2004 gn->add_child(make_label("c", Variant::REAL));
2005 } else {
2006 float v = graph->default_get_value(type, p_id, 2);
2007 gn->add_child(make_editor(String("c: ") + Variant(v), gn, p_id, 2, Variant::REAL, hint_slider));
2008 }
2009
2010 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2011 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
2012 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
2013
2014 } break; // scalar interpolation (with optional curve)
2015 case ShaderGraph::NODE_VEC_INTERP: {
2016
2017 gn->set_title("VecInterp");
2018 HBoxContainer *hbc = memnew(HBoxContainer);
2019 if (graph->is_slot_connected(type, p_id, 0)) {
2020 hbc->add_child(make_label("a", Variant::VECTOR3));
2021 } else {
2022 Vector3 v = graph->default_get_value(type, p_id, 0);
2023 hbc->add_child(make_editor(String("a: ") + v, gn, p_id, 0, Variant::VECTOR3));
2024 }
2025 hbc->add_spacer();
2026 hbc->add_child(memnew(Label("interp")));
2027 gn->add_child(hbc);
2028 if (graph->is_slot_connected(type, p_id, 1)) {
2029 gn->add_child(make_label("b", Variant::VECTOR3));
2030 } else {
2031 Vector3 v = graph->default_get_value(type, p_id, 1);
2032 gn->add_child(make_editor(String("b: ") + v, gn, p_id, 1, Variant::VECTOR3));
2033 }
2034 if (graph->is_slot_connected(type, p_id, 2)) {
2035 gn->add_child(make_label("c", Variant::REAL));
2036 } else {
2037 float v = graph->default_get_value(type, p_id, 2);
2038 gn->add_child(make_editor(String("c: ") + Variant(v), gn, p_id, 2, Variant::REAL, hint_slider));
2039 }
2040
2041 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2042 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], false, 0, Color());
2043 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], false, 0, Color());
2044
2045 } break; // vec3 interpolation (with optional curve)
2046 case ShaderGraph::NODE_COLOR_RAMP: {
2047
2048 gn->set_title("ColorRamp");
2049 GraphColorRampEdit *ramp = memnew(GraphColorRampEdit);
2050
2051 DVector<real_t> offsets = graph->color_ramp_node_get_offsets(type, p_id);
2052 DVector<Color> colors = graph->color_ramp_node_get_colors(type, p_id);
2053
2054 int oc = offsets.size();
2055
2056 if (oc) {
2057 DVector<real_t>::Read rofs = offsets.read();
2058 DVector<Color>::Read rcol = colors.read();
2059
2060 Vector<float> ofsv;
2061 Vector<Color> colorv;
2062 for (int i = 0; i < oc; i++) {
2063 ofsv.push_back(rofs[i]);
2064 colorv.push_back(rcol[i]);
2065 }
2066
2067 ramp->set_ramp(ofsv, colorv);
2068 }
2069
2070 ramp->connect("ramp_changed", this, "_color_ramp_changed", varray(p_id, ramp));
2071 ramp->set_custom_minimum_size(Size2(128, 1));
2072 gn->add_child(ramp);
2073
2074 HBoxContainer *hbc = memnew(HBoxContainer);
2075 hbc->add_constant_override("separation", 0);
2076 if (graph->is_slot_connected(type, p_id, 0)) {
2077 hbc->add_child(make_label("c", Variant::REAL));
2078 } else {
2079 float v = graph->default_get_value(type, p_id, 0);
2080 hbc->add_child(make_editor(String("c: ") + Variant(v), gn, p_id, 0, Variant::REAL, hint_slider));
2081 }
2082 hbc->add_spacer();
2083 Label *l = memnew(Label("rgb"));
2084 l->set_align(Label::ALIGN_RIGHT);
2085 hbc->add_child(l);
2086 gn->add_child(hbc);
2087 l = memnew(Label("alpha"));
2088 l->set_align(Label::ALIGN_RIGHT);
2089 gn->add_child(l);
2090
2091 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2092 gn->set_slot(2, false, ShaderGraph::SLOT_MAX, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2093
2094 } break; // scalar interpolation (with optional curve)
2095 case ShaderGraph::NODE_CURVE_MAP: {
2096
2097 gn->set_title("CurveMap");
2098 GraphCurveMapEdit *map = memnew(GraphCurveMapEdit);
2099
2100 DVector<Vector2> points = graph->curve_map_node_get_points(type, p_id);
2101
2102 int oc = points.size();
2103
2104 if (oc) {
2105 DVector<Vector2>::Read rofs = points.read();
2106
2107 Vector<Vector2> ofsv;
2108 for (int i = 0; i < oc; i++) {
2109 ofsv.push_back(rofs[i]);
2110 }
2111
2112 map->set_points(ofsv);
2113 }
2114 map->connect("curve_changed", this, "_curve_changed", varray(p_id, map));
2115
2116 //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map));
2117 map->set_custom_minimum_size(Size2(128, 64));
2118 gn->add_child(map);
2119
2120 HBoxContainer *hbc = memnew(HBoxContainer);
2121 hbc->add_constant_override("separation", 0);
2122 if (graph->is_slot_connected(type, p_id, 0)) {
2123 hbc->add_child(make_label("c", Variant::REAL));
2124 } else {
2125 float v = graph->default_get_value(type, p_id, 0);
2126 hbc->add_child(make_editor(String("c: ") + Variant(v), gn, p_id, 0, Variant::REAL, hint_slider));
2127 }
2128 hbc->add_spacer();
2129 Label *l = memnew(Label("cmap"));
2130 l->set_align(Label::ALIGN_RIGHT);
2131 hbc->add_child(l);
2132 gn->add_child(hbc);
2133
2134 gn->set_slot(1, true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR], true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2135
2136 } break; // scalar interpolation (with optional curve)
2137
2138 case ShaderGraph::NODE_SCALAR_INPUT: {
2139
2140 gn->set_title("ScalarUniform");
2141 LineEdit *le = memnew(LineEdit);
2142 gn->add_child(le);
2143 le->set_text(graph->input_node_get_name(type, p_id));
2144 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2145 SpinBox *sb = memnew(SpinBox);
2146 sb->set_min(-100000);
2147 sb->set_max(100000);
2148 sb->set_step(0.001);
2149 sb->set_val(graph->scalar_input_node_get_value(type, p_id));
2150 sb->connect("value_changed", this, "_scalar_input_changed", varray(p_id));
2151 gn->add_child(sb);
2152 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2153
2154 } break; // scalar uniform (assignable in material)
2155 case ShaderGraph::NODE_VEC_INPUT: {
2156
2157 gn->set_title("VectorUniform");
2158 LineEdit *le = memnew(LineEdit);
2159 gn->add_child(le);
2160 le->set_text(graph->input_node_get_name(type, p_id));
2161 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2162 Array v3p(true);
2163 for (int i = 0; i < 3; i++) {
2164 HBoxContainer *hbc = memnew(HBoxContainer);
2165 Label *l = memnew(Label);
2166 l->set_text(String::chr('X' + i));
2167 hbc->add_child(l);
2168 SpinBox *sb = memnew(SpinBox);
2169 sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
2170 sb->set_min(-100000);
2171 sb->set_max(100000);
2172 sb->set_step(0.001);
2173 sb->set_val(graph->vec_input_node_get_value(type, p_id)[i]);
2174 sb->connect("value_changed", this, "_vec_input_changed", varray(p_id, v3p));
2175 v3p.push_back(sb);
2176 hbc->add_child(sb);
2177 gn->add_child(hbc);
2178 }
2179 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2180
2181 } break; // vec3 uniform (assignable in material)
2182 case ShaderGraph::NODE_RGB_INPUT: {
2183
2184 gn->set_title("ColorUniform");
2185 LineEdit *le = memnew(LineEdit);
2186 gn->add_child(le);
2187 le->set_text(graph->input_node_get_name(type, p_id));
2188 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2189 ColorPickerButton *cpb = memnew(ColorPickerButton);
2190 cpb->set_color(graph->rgb_input_node_get_value(type, p_id));
2191 cpb->connect("color_changed", this, "_rgb_input_changed", varray(p_id));
2192 gn->add_child(cpb);
2193 Label *l = memnew(Label);
2194 l->set_text("RGB");
2195 l->set_align(Label::ALIGN_RIGHT);
2196 gn->add_child(l);
2197 l = memnew(Label);
2198 l->set_text("Alpha");
2199 l->set_align(Label::ALIGN_RIGHT);
2200 gn->add_child(l);
2201
2202 gn->set_slot(2, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2203 gn->set_slot(3, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2204
2205 } break; // color uniform (assignable in material)
2206 case ShaderGraph::NODE_XFORM_INPUT: {
2207 gn->set_title("XFUniform");
2208 LineEdit *le = memnew(LineEdit);
2209 gn->add_child(le);
2210 le->set_text(graph->input_node_get_name(type, p_id));
2211 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2212 ToolButton *edit = memnew(ToolButton);
2213 edit->set_text("edit..");
2214 edit->connect("pressed", this, "_xform_input_changed", varray(p_id, edit));
2215 gn->add_child(edit);
2216 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_XFORM, typecol[ShaderGraph::SLOT_TYPE_XFORM]);
2217
2218 } break; // mat4 uniform (assignable in material)
2219 case ShaderGraph::NODE_TEXTURE_INPUT: {
2220
2221 gn->set_title("TexUniform");
2222 LineEdit *le = memnew(LineEdit);
2223 gn->add_child(le);
2224 le->set_text(graph->input_node_get_name(type, p_id));
2225 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2226 TextureFrame *tex = memnew(TextureFrame);
2227 tex->set_expand(true);
2228 tex->set_custom_minimum_size(Size2(80, 80));
2229 tex->set_drag_forwarding(this);
2230 gn->add_child(tex);
2231 tex->set_ignore_mouse(false);
2232 tex->set_texture(graph->texture_input_node_get_value(type, p_id));
2233 ToolButton *edit = memnew(ToolButton);
2234 edit->set_text("edit..");
2235 edit->connect("pressed", this, "_tex_edited", varray(p_id, edit));
2236 gn->add_child(edit);
2237
2238 HBoxContainer *hbc = memnew(HBoxContainer);
2239 hbc->add_constant_override("separation", 0);
2240 if (graph->is_slot_connected(type, p_id, 0)) {
2241 hbc->add_child(make_label("UV", Variant::VECTOR3));
2242 } else {
2243 Vector3 v = graph->default_get_value(type, p_id, 0);
2244 hbc->add_child(make_editor(String("UV: ") + v, gn, p_id, 0, Variant::VECTOR3));
2245 }
2246 hbc->add_spacer();
2247 Label *l = memnew(Label("RGB"));
2248 l->set_align(Label::ALIGN_RIGHT);
2249 hbc->add_child(l);
2250 gn->add_child(hbc);
2251 l = memnew(Label);
2252 l->set_text("Alpha");
2253 l->set_align(Label::ALIGN_RIGHT);
2254 gn->add_child(l);
2255
2256 gn->set_slot(3, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2257 gn->set_slot(4, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2258
2259 } break; // texture input (assignable in material)
2260 case ShaderGraph::NODE_CUBEMAP_INPUT: {
2261
2262 gn->set_title("TexUniform");
2263 LineEdit *le = memnew(LineEdit);
2264 gn->add_child(le);
2265 le->set_text(graph->input_node_get_name(type, p_id));
2266 le->connect("text_entered", this, "_input_name_changed", varray(p_id, le));
2267
2268 ToolButton *edit = memnew(ToolButton);
2269 edit->set_text("edit..");
2270 edit->connect("pressed", this, "_cube_edited", varray(p_id, edit));
2271 gn->add_child(edit);
2272
2273 HBoxContainer *hbc = memnew(HBoxContainer);
2274 hbc->add_constant_override("separation", 0);
2275 if (graph->is_slot_connected(type, p_id, 0)) {
2276 hbc->add_child(make_label("UV", Variant::VECTOR3));
2277 } else {
2278 Vector3 v = graph->default_get_value(type, p_id, 0);
2279 hbc->add_child(make_editor(String("UV: ") + v, gn, p_id, 0, Variant::VECTOR3));
2280 }
2281 hbc->add_spacer();
2282 Label *l = memnew(Label("RGB"));
2283 l->set_align(Label::ALIGN_RIGHT);
2284 hbc->add_child(l);
2285 gn->add_child(hbc);
2286 l = memnew(Label);
2287 l->set_text("Alpha");
2288 l->set_align(Label::ALIGN_RIGHT);
2289 gn->add_child(l);
2290
2291 gn->set_slot(2, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2292 gn->set_slot(3, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2293
2294 } break; // cubemap input (assignable in material)
2295 case ShaderGraph::NODE_DEFAULT_TEXTURE: {
2296
2297 gn->set_title("CanvasItemTex");
2298 HBoxContainer *hbc = memnew(HBoxContainer);
2299 hbc->add_constant_override("separation", 0);
2300 if (graph->is_slot_connected(type, p_id, 0)) {
2301 hbc->add_child(make_label("UV", Variant::VECTOR3));
2302 } else {
2303 Vector3 v = graph->default_get_value(type, p_id, 0);
2304 hbc->add_child(make_editor(String("UV: ") + v, gn, p_id, 0, Variant::VECTOR3));
2305 }
2306 hbc->add_spacer();
2307 Label *l = memnew(Label("RGB"));
2308 l->set_align(Label::ALIGN_RIGHT);
2309 hbc->add_child(l);
2310 gn->add_child(hbc);
2311 l = memnew(Label);
2312 l->set_text("Alpha");
2313 l->set_align(Label::ALIGN_RIGHT);
2314 gn->add_child(l);
2315
2316 gn->set_slot(0, true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC], true, ShaderGraph::SLOT_TYPE_VEC, typecol[ShaderGraph::SLOT_TYPE_VEC]);
2317 gn->set_slot(1, false, 0, Color(), true, ShaderGraph::SLOT_TYPE_SCALAR, typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
2318
2319 } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
2320
2321 case ShaderGraph::NODE_OUTPUT: {
2322 gn->set_title("Output");
2323 gn->set_show_close_button(false);
2324
2325 List<ShaderGraph::SlotInfo> si;
2326 ShaderGraph::get_input_output_node_slot_info(graph->get_mode(), type, &si);
2327
2328 Array colors;
2329 colors.push_back("Color");
2330 colors.push_back("LightColor");
2331 colors.push_back("Light");
2332 colors.push_back("ShadowColor");
2333 colors.push_back("Diffuse");
2334 colors.push_back("Specular");
2335 colors.push_back("Emmision");
2336 Array reals;
2337 reals.push_back("Alpha");
2338 reals.push_back("DiffuseAlpha");
2339 reals.push_back("NormalMapDepth");
2340 reals.push_back("SpecExp");
2341 reals.push_back("Glow");
2342 reals.push_back("ShadeParam");
2343 reals.push_back("SpecularExp");
2344 reals.push_back("LightAlpha");
2345 reals.push_back("ShadowAlpha");
2346 reals.push_back("PointSize");
2347 reals.push_back("Discard");
2348
2349 int idx = 0;
2350 for (List<ShaderGraph::SlotInfo>::Element *E = si.front(); E; E = E->next()) {
2351 ShaderGraph::SlotInfo &s = E->get();
2352 if (s.dir == ShaderGraph::SLOT_OUT) {
2353 Variant::Type v;
2354 if (colors.find(s.name) >= 0)
2355 v = Variant::COLOR;
2356 else if (reals.find(s.name) >= 0)
2357 v = Variant::REAL;
2358 else
2359 v = Variant::VECTOR3;
2360 gn->add_child(make_label(s.name, v));
2361 gn->set_slot(idx, true, s.type, typecol[s.type], false, 0, Color());
2362 idx++;
2363 }
2364 }
2365
2366 } break; // output (case Shader type dependent)
2367 case ShaderGraph::NODE_COMMENT: {
2368 gn->set_title("Comment");
2369 TextEdit *te = memnew(TextEdit);
2370 te->set_custom_minimum_size(Size2(100, 100));
2371 gn->add_child(te);
2372 te->set_text(graph->comment_node_get_text(type, p_id));
2373 te->connect("text_changed", this, "_comment_edited", varray(p_id, te));
2374
2375 } break; // comment
2376 }
2377
2378 gn->connect("dragged", this, "_node_moved", varray(p_id));
2379 gn->connect("close_request", this, "_node_removed", varray(p_id), CONNECT_DEFERRED);
2380 graph_edit->add_child(gn);
2381 node_map[p_id] = gn;
2382 gn->set_offset(graph->node_get_pos(type, p_id));
2383 }
2384
_update_graph()2385 void ShaderGraphView::_update_graph() {
2386
2387 if (block_update)
2388 return;
2389
2390 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next()) {
2391
2392 memdelete(E->get());
2393 }
2394
2395 node_map.clear();
2396
2397 if (!graph.is_valid())
2398 return;
2399
2400 List<int> nl;
2401 graph->get_node_list(type, &nl);
2402
2403 for (List<int>::Element *E = nl.front(); E; E = E->next()) {
2404
2405 _create_node(E->get());
2406 }
2407 graph_edit->clear_connections();
2408
2409 List<ShaderGraph::Connection> connections;
2410 graph->get_node_connections(type, &connections);
2411 for (List<ShaderGraph::Connection>::Element *E = connections.front(); E; E = E->next()) {
2412
2413 ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id));
2414 graph_edit->connect_node(node_map[E->get().src_id]->get_name(), E->get().src_slot, node_map[E->get().dst_id]->get_name(), E->get().dst_slot);
2415 }
2416 }
2417
_sg_updated()2418 void ShaderGraphView::_sg_updated() {
2419
2420 if (!graph.is_valid())
2421 return;
2422 switch (graph->get_graph_error(type)) {
2423 case ShaderGraph::GRAPH_OK: status->set_text(""); break;
2424 case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text(TTR("Error: Cyclic Connection Link")); break;
2425 case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text(TTR("Error: Missing Input Connections")); break;
2426 }
2427 }
2428
get_drag_data_fw(const Point2 & p_point,Control * p_from)2429 Variant ShaderGraphView::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
2430 TextureFrame *frame = p_from->cast_to<TextureFrame>();
2431 if (!frame)
2432 return Variant();
2433
2434 if (!frame->get_texture().is_valid())
2435 return Variant();
2436
2437 RES res = frame->get_texture();
2438 return EditorNode::get_singleton()->drag_resource(res, p_from);
2439
2440 return Variant();
2441 }
2442
can_drop_data_fw(const Point2 & p_point,const Variant & p_data,Control * p_from) const2443 bool ShaderGraphView::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
2444 if (p_data.get_type() != Variant::DICTIONARY)
2445 return false;
2446
2447 Dictionary d = p_data;
2448
2449 if (d.has("type")) {
2450 if (d["type"] == "resource" && d.has("resource")) {
2451 Variant val = d["resource"];
2452
2453 if (val.get_type() == Variant::OBJECT) {
2454 RES res = val;
2455 if (res.is_valid() && res->cast_to<Texture>())
2456 return true;
2457 }
2458 } else if (d["type"] == "files" && d.has("files")) {
2459 Vector<String> files = d["files"];
2460 if (files.size() != 1)
2461 return false;
2462 return (ResourceLoader::get_resource_type(files[0]) == "ImageTexture");
2463 }
2464 }
2465
2466 return false;
2467 }
2468
drop_data_fw(const Point2 & p_point,const Variant & p_data,Control * p_from)2469 void ShaderGraphView::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
2470 if (!can_drop_data_fw(p_point, p_data, p_from))
2471 return;
2472
2473 TextureFrame *frame = p_from->cast_to<TextureFrame>();
2474 if (!frame)
2475 return;
2476
2477 Dictionary d = p_data;
2478 Ref<Texture> tex;
2479
2480 if (d.has("type")) {
2481 if (d["type"] == "resource" && d.has("resource")) {
2482 Variant val = d["resource"];
2483
2484 if (val.get_type() == Variant::OBJECT) {
2485 RES res = val;
2486 if (res.is_valid())
2487 tex = Ref<Texture>(res->cast_to<Texture>());
2488 }
2489 } else if (d["type"] == "files" && d.has("files")) {
2490 Vector<String> files = d["files"];
2491 RES res = ResourceLoader::load(files[0]);
2492 if (res.is_valid())
2493 tex = Ref<Texture>(res->cast_to<Texture>());
2494 }
2495 }
2496
2497 if (!tex.is_valid()) return;
2498
2499 GraphNode *gn = frame->get_parent()->cast_to<GraphNode>();
2500 if (!gn) return;
2501
2502 int id = -1;
2503 for (Map<int, GraphNode *>::Element *E = node_map.front(); E; E = E->next())
2504 if (E->get() == gn) {
2505 id = E->key();
2506 break;
2507 }
2508 print_line(String::num(double(id)));
2509 if (id < 0) return;
2510
2511 if (graph->node_get_type(type, id) == ShaderGraph::NODE_TEXTURE_INPUT) {
2512
2513 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
2514 ur->create_action(TTR("Change Texture Uniform"));
2515 ur->add_do_method(graph.ptr(), "texture_input_node_set_value", type, id, tex);
2516 ur->add_undo_method(graph.ptr(), "texture_input_node_set_value", type, id, graph->texture_input_node_get_value(type, id));
2517 ur->add_do_method(this, "_update_graph");
2518 ur->add_undo_method(this, "_update_graph");
2519 ur->commit_action();
2520 }
2521 }
2522
set_graph(Ref<ShaderGraph> p_graph)2523 void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph) {
2524
2525 if (graph.is_valid()) {
2526 graph->disconnect("updated", this, "_sg_updated");
2527 }
2528 graph = p_graph;
2529 if (graph.is_valid()) {
2530 graph->connect("updated", this, "_sg_updated");
2531 }
2532 _update_graph();
2533 _sg_updated();
2534 }
2535
_notification(int p_what)2536 void ShaderGraphView::_notification(int p_what) {
2537
2538 if (p_what == NOTIFICATION_ENTER_TREE) {
2539
2540 ped_popup->connect("variant_changed", this, "_variant_edited");
2541 }
2542 }
2543
add_node(int p_type,const Vector2 & location)2544 void ShaderGraphView::add_node(int p_type, const Vector2 &location) {
2545
2546 if (p_type == ShaderGraph::NODE_INPUT && graph->node_count(type, p_type) > 0)
2547 return;
2548
2549 List<int> existing;
2550 graph->get_node_list(type, &existing);
2551 existing.sort();
2552 int newid = 1;
2553 for (List<int>::Element *E = existing.front(); E; E = E->next()) {
2554 if (!E->next() || (E->get() + 1 != E->next()->get())) {
2555 newid = E->get() + 1;
2556 break;
2557 }
2558 }
2559
2560 Vector2 init_ofs = location;
2561 while (true) {
2562 bool valid = true;
2563 for (List<int>::Element *E = existing.front(); E; E = E->next()) {
2564 Vector2 pos = graph->node_get_pos(type, E->get());
2565 if (init_ofs == pos) {
2566 init_ofs += Vector2(20, 20);
2567 valid = false;
2568 break;
2569 }
2570 }
2571
2572 if (valid)
2573 break;
2574 }
2575 UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
2576 ur->create_action(TTR("Add Shader Graph Node"));
2577 ur->add_do_method(graph.ptr(), "node_add", type, p_type, newid);
2578 ur->add_do_method(graph.ptr(), "node_set_pos", type, newid, init_ofs);
2579 ur->add_undo_method(graph.ptr(), "node_remove", type, newid);
2580 ur->add_do_method(this, "_update_graph");
2581 ur->add_undo_method(this, "_update_graph");
2582 ur->commit_action();
2583 }
2584
_bind_methods()2585 void ShaderGraphView::_bind_methods() {
2586
2587 ObjectTypeDB::bind_method("_update_graph", &ShaderGraphView::_update_graph);
2588 ObjectTypeDB::bind_method("_begin_node_move", &ShaderGraphView::_begin_node_move);
2589 ObjectTypeDB::bind_method("_node_moved", &ShaderGraphView::_node_moved);
2590 ObjectTypeDB::bind_method("_end_node_move", &ShaderGraphView::_end_node_move);
2591 ObjectTypeDB::bind_method("_move_node", &ShaderGraphView::_move_node);
2592 ObjectTypeDB::bind_method("_node_removed", &ShaderGraphView::_node_removed);
2593 ObjectTypeDB::bind_method("_connection_request", &ShaderGraphView::_connection_request);
2594 ObjectTypeDB::bind_method("_disconnection_request", &ShaderGraphView::_disconnection_request);
2595 ObjectTypeDB::bind_method("_duplicate_nodes_request", &ShaderGraphView::_duplicate_nodes_request);
2596 ObjectTypeDB::bind_method("_duplicate_nodes", &ShaderGraphView::_duplicate_nodes);
2597 ObjectTypeDB::bind_method("_delete_nodes_request", &ShaderGraphView::_delete_nodes_request);
2598
2599 ObjectTypeDB::bind_method("_default_changed", &ShaderGraphView::_default_changed);
2600 ObjectTypeDB::bind_method("_scalar_const_changed", &ShaderGraphView::_scalar_const_changed);
2601 ObjectTypeDB::bind_method("_vec_const_changed", &ShaderGraphView::_vec_const_changed);
2602 ObjectTypeDB::bind_method("_rgb_const_changed", &ShaderGraphView::_rgb_const_changed);
2603 ObjectTypeDB::bind_method("_xform_const_changed", &ShaderGraphView::_xform_const_changed);
2604 ObjectTypeDB::bind_method("_scalar_op_changed", &ShaderGraphView::_scalar_op_changed);
2605 ObjectTypeDB::bind_method("_vec_op_changed", &ShaderGraphView::_vec_op_changed);
2606 ObjectTypeDB::bind_method("_vec_scalar_op_changed", &ShaderGraphView::_vec_scalar_op_changed);
2607 ObjectTypeDB::bind_method("_rgb_op_changed", &ShaderGraphView::_rgb_op_changed);
2608 ObjectTypeDB::bind_method("_xform_inv_rev_changed", &ShaderGraphView::_xform_inv_rev_changed);
2609 ObjectTypeDB::bind_method("_scalar_func_changed", &ShaderGraphView::_scalar_func_changed);
2610 ObjectTypeDB::bind_method("_vec_func_changed", &ShaderGraphView::_vec_func_changed);
2611 ObjectTypeDB::bind_method("_scalar_input_changed", &ShaderGraphView::_scalar_input_changed);
2612 ObjectTypeDB::bind_method("_vec_input_changed", &ShaderGraphView::_vec_input_changed);
2613 ObjectTypeDB::bind_method("_xform_input_changed", &ShaderGraphView::_xform_input_changed);
2614 ObjectTypeDB::bind_method("_rgb_input_changed", &ShaderGraphView::_rgb_input_changed);
2615 ObjectTypeDB::bind_method("_tex_input_change", &ShaderGraphView::_tex_input_change);
2616 ObjectTypeDB::bind_method("_cube_input_change", &ShaderGraphView::_cube_input_change);
2617 ObjectTypeDB::bind_method("_input_name_changed", &ShaderGraphView::_input_name_changed);
2618 ObjectTypeDB::bind_method("_tex_edited", &ShaderGraphView::_tex_edited);
2619 ObjectTypeDB::bind_method("_variant_edited", &ShaderGraphView::_variant_edited);
2620 ObjectTypeDB::bind_method("_cube_edited", &ShaderGraphView::_cube_edited);
2621 ObjectTypeDB::bind_method("_comment_edited", &ShaderGraphView::_comment_edited);
2622 ObjectTypeDB::bind_method("_color_ramp_changed", &ShaderGraphView::_color_ramp_changed);
2623 ObjectTypeDB::bind_method("_curve_changed", &ShaderGraphView::_curve_changed);
2624
2625 ObjectTypeDB::bind_method(_MD("get_drag_data_fw"), &ShaderGraphView::get_drag_data_fw);
2626 ObjectTypeDB::bind_method(_MD("can_drop_data_fw"), &ShaderGraphView::can_drop_data_fw);
2627 ObjectTypeDB::bind_method(_MD("drop_data_fw"), &ShaderGraphView::drop_data_fw);
2628
2629 ObjectTypeDB::bind_method("_sg_updated", &ShaderGraphView::_sg_updated);
2630 }
2631
ShaderGraphView(ShaderGraph::ShaderType p_type)2632 ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) {
2633
2634 type = p_type;
2635 graph_edit = memnew(GraphEdit);
2636 block_update = false;
2637 ped_popup = memnew(CustomPropertyEditor);
2638 graph_edit->add_child(ped_popup);
2639 status = memnew(Label);
2640 graph_edit->get_top_layer()->add_child(status);
2641 graph_edit->connect("_begin_node_move", this, "_begin_node_move");
2642 graph_edit->connect("_end_node_move", this, "_end_node_move");
2643 status->set_pos(Vector2(5, 5));
2644 status->add_color_override("font_color_shadow", Color(0, 0, 0));
2645 status->add_color_override("font_color", Color(1, 0.4, 0.3));
2646 status->add_constant_override("shadow_as_outline", 1);
2647 status->add_constant_override("shadow_offset_x", 2);
2648 status->add_constant_override("shadow_offset_y", 2);
2649 status->set_text("");
2650 }
2651
2652 //////////////edit//////////////
edit(Ref<ShaderGraph> p_shader)2653 void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
2654
2655 for (int i = 0; i < ShaderGraph::SHADER_TYPE_MAX; i++) {
2656 graph_edits[i]->set_graph(p_shader);
2657 }
2658 }
2659
_add_node(int p_type)2660 void ShaderGraphEditor::_add_node(int p_type) {
2661
2662 ShaderGraph::ShaderType shader_type = ShaderGraph::ShaderType(tabs->get_current_tab());
2663 graph_edits[shader_type]->add_node(p_type, next_location);
2664 }
2665
_popup_requested(const Vector2 & p_position)2666 void ShaderGraphEditor::_popup_requested(const Vector2 &p_position) {
2667 Vector2 scroll_ofs = graph_edits[tabs->get_current_tab()]->get_graph_edit()->get_scroll_ofs();
2668 next_location = get_local_mouse_pos() + scroll_ofs;
2669 popup->set_global_pos(p_position);
2670 popup->set_size(Size2(200, 0));
2671 popup->popup();
2672 popup->call_deferred("grab_click_focus");
2673 popup->set_invalidate_click_until_motion();
2674 }
2675
_notification(int p_what)2676 void ShaderGraphEditor::_notification(int p_what) {
2677 if (p_what == NOTIFICATION_ENTER_TREE) {
2678
2679 for (int i = 0; i < ShaderGraph::NODE_TYPE_MAX; i++) {
2680
2681 if (i == ShaderGraph::NODE_OUTPUT)
2682 continue;
2683 if (!_2d && i == ShaderGraph::NODE_DEFAULT_TEXTURE)
2684 continue;
2685
2686 String nn = node_names[i];
2687 String ic = nn.get_slice(":", 0);
2688 String v = nn.get_slice(":", 1);
2689 bool addsep = false;
2690 if (nn.ends_with(":")) {
2691 addsep = true;
2692 }
2693 popup->add_icon_item(get_icon(ic, "EditorIcons"), v, i);
2694 if (addsep)
2695 popup->add_separator();
2696 }
2697 popup->connect("item_pressed", this, "_add_node");
2698 }
2699 }
2700
_bind_methods()2701 void ShaderGraphEditor::_bind_methods() {
2702
2703 ObjectTypeDB::bind_method("_add_node", &ShaderGraphEditor::_add_node);
2704 ObjectTypeDB::bind_method("_popup_requested", &ShaderGraphEditor::_popup_requested);
2705 }
2706
2707 const char *ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX] = {
2708 ("GraphInput:Input"), // all inputs (shader type dependent)
2709 ("GraphScalar:Scalar Constant"), //scalar constant
2710 ("GraphVector:Vector Constant"), //vec3 constant
2711 ("GraphRgb:RGB Constant"), //rgb constant (shows a color picker instead)
2712 ("GraphXform:XForm Constant"), // 4x4 matrix constant
2713 ("GraphTime:Time:"), // time in seconds
2714 ("GraphTexscreen:Screen Sample"), // screen texture sampler (takes uv) (only usable in fragment shader)
2715 ("GraphScalarOp:Scalar Operator"), // scalar vs scalar op (mul", add", div", etc)
2716 ("GraphVecOp:Vector Operator"), // vec3 vs vec3 op (mul",ad",div",crossprod",etc)
2717 ("GraphVecScalarOp:Scalar+Vector Operator"), // vec3 vs scalar op (mul", add", div", etc)
2718 ("GraphRgbOp:RGB Operator:"), // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc.
2719 ("GraphXformMult:XForm Multiply"), // mat4 x mat4
2720 ("GraphXformVecMult:XForm+Vector Multiply"), // mat4 x vec3 mult (with no-translation option)
2721 ("GraphXformVecImult:Form+Vector InvMultiply:"), // mat4 x vec3 inverse mult (with no-translation option)
2722 ("GraphXformScalarFunc:Scalar Function"), // scalar function (sin", cos", etc)
2723 ("GraphXformVecFunc:Vector Function"), // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc)
2724 ("GraphVecLength:Vector Length"), // vec3 length
2725 ("GraphVecDp:Dot Product:"), // vec3 . vec3 (dot product -> scalar output)
2726 ("GraphVecToScalars:Vector -> Scalars"), // 1 vec3 input", 3 scalar outputs
2727 ("GraphScalarsToVec:Scalars -> Vector"), // 3 scalar input", 1 vec3 output
2728 ("GraphXformToVecs:XForm -> Vectors"), // 3 vec input", 1 xform output
2729 ("GraphVecsToXform:Vectors -> XForm:"), // 3 vec input", 1 xform output
2730 ("GraphScalarInterp:Scalar Interpolate"), // scalar interpolation (with optional curve)
2731 ("GraphVecInterp:Vector Interpolate:"), // vec3 interpolation (with optional curve)
2732 ("GraphColorRamp:Color Ramp"), // vec3 interpolation (with optional curve)
2733 ("GraphCurveMap:Curve Remap:"), // vec3 interpolation (with optional curve)
2734 ("GraphScalarUniform:Scalar Uniform"), // scalar uniform (assignable in material)
2735 ("GraphVectorUniform:Vector Uniform"), // vec3 uniform (assignable in material)
2736 ("GraphRgbUniform:RGB Uniform"), // color uniform (assignable in material)
2737 ("GraphXformUniform:XForm Uniform"), // mat4 uniform (assignable in material)
2738 ("GraphTextureUniform:Texture Uniform"), // texture input (assignable in material)
2739 ("GraphCubeUniform:CubeMap Uniform:"), // cubemap input (assignable in material)
2740 ("GraphDefaultTexture:CanvasItem Texture:"), // cubemap input (assignable in material)
2741 ("Output"), // output (shader type dependent)
2742 ("GraphComment:Comment"), // comment
2743
2744 };
ShaderGraphEditor(bool p_2d)2745 ShaderGraphEditor::ShaderGraphEditor(bool p_2d) {
2746 _2d = p_2d;
2747
2748 popup = memnew(PopupMenu);
2749 add_child(popup);
2750
2751 tabs = memnew(TabContainer);
2752 tabs->set_v_size_flags(SIZE_EXPAND_FILL);
2753 add_child(tabs);
2754 const char *sname[ShaderGraph::SHADER_TYPE_MAX] = {
2755 "Vertex",
2756 "Fragment",
2757 "Light"
2758 };
2759 for (int i = 0; i < ShaderGraph::SHADER_TYPE_MAX; i++) {
2760
2761 graph_edits[i] = memnew(ShaderGraphView(ShaderGraph::ShaderType(i)));
2762 add_child(graph_edits[i]);
2763 graph_edits[i]->get_graph_edit()->set_name(sname[i]);
2764 tabs->add_child(graph_edits[i]->get_graph_edit());
2765 graph_edits[i]->get_graph_edit()->connect("connection_request", graph_edits[i], "_connection_request");
2766 graph_edits[i]->get_graph_edit()->connect("disconnection_request", graph_edits[i], "_disconnection_request");
2767 graph_edits[i]->get_graph_edit()->connect("duplicate_nodes_request", graph_edits[i], "_duplicate_nodes_request");
2768 graph_edits[i]->get_graph_edit()->connect("popup_request", this, "_popup_requested");
2769 graph_edits[i]->get_graph_edit()->connect("delete_nodes_request", graph_edits[i], "_delete_nodes_request");
2770 graph_edits[i]->get_graph_edit()->set_right_disconnects(true);
2771 }
2772
2773 tabs->set_current_tab(1);
2774
2775 set_custom_minimum_size(Size2(100, 300));
2776 }
2777
edit(Object * p_object)2778 void ShaderGraphEditorPlugin::edit(Object *p_object) {
2779
2780 shader_editor->edit(p_object->cast_to<ShaderGraph>());
2781 }
2782
handles(Object * p_object) const2783 bool ShaderGraphEditorPlugin::handles(Object *p_object) const {
2784
2785 ShaderGraph *shader = p_object->cast_to<ShaderGraph>();
2786 if (!shader)
2787 return false;
2788 if (_2d)
2789 return shader->get_mode() == Shader::MODE_CANVAS_ITEM;
2790 else
2791 return shader->get_mode() == Shader::MODE_MATERIAL;
2792 }
2793
make_visible(bool p_visible)2794 void ShaderGraphEditorPlugin::make_visible(bool p_visible) {
2795
2796 if (p_visible) {
2797 shader_editor->show();
2798 } else {
2799
2800 shader_editor->hide();
2801 }
2802 }
2803
ShaderGraphEditorPlugin(EditorNode * p_node,bool p_2d)2804 ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) {
2805
2806 _2d = p_2d;
2807 editor = p_node;
2808 shader_editor = memnew(ShaderGraphEditor(p_2d));
2809 shader_editor->hide();
2810 if (p_2d)
2811 CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(shader_editor);
2812 else
2813 SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor);
2814
2815 // editor->get_viewport()->add_child(shader_editor);
2816 // shader_editor->set_area_as_parent_rect();
2817 // shader_editor->hide();
2818 }
2819
~ShaderGraphEditorPlugin()2820 ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin() {
2821 }
2822