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