1 /*************************************************************************/
2 /*  visual_shader_editor_plugin.cpp                                      */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 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 
31 #include "visual_shader_editor_plugin.h"
32 
33 #include "core/io/resource_loader.h"
34 #include "core/math/math_defs.h"
35 #include "core/os/input.h"
36 #include "core/os/keyboard.h"
37 #include "core/project_settings.h"
38 #include "editor/editor_log.h"
39 #include "editor/editor_properties.h"
40 #include "editor/editor_scale.h"
41 #include "scene/animation/animation_player.h"
42 #include "scene/gui/menu_button.h"
43 #include "scene/gui/panel.h"
44 #include "scene/main/viewport.h"
45 #include "scene/resources/visual_shader_nodes.h"
46 #include "servers/visual/shader_types.h"
47 
create_editor(const Ref<Resource> & p_parent_resource,const Ref<VisualShaderNode> & p_node)48 Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
49 
50 	if (get_script_instance()) {
51 		return get_script_instance()->call("create_editor", p_parent_resource, p_node);
52 	}
53 	return NULL;
54 }
55 
_bind_methods()56 void VisualShaderNodePlugin::_bind_methods() {
57 
58 	BIND_VMETHOD(MethodInfo(Variant::OBJECT, "create_editor", PropertyInfo(Variant::OBJECT, "parent_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::OBJECT, "for_node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode")));
59 }
60 
61 ///////////////////
62 
edit(VisualShader * p_visual_shader)63 void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
64 
65 	bool changed = false;
66 	if (p_visual_shader) {
67 		if (visual_shader.is_null()) {
68 			changed = true;
69 		} else {
70 			if (visual_shader.ptr() != p_visual_shader) {
71 				changed = true;
72 			}
73 		}
74 		visual_shader = Ref<VisualShader>(p_visual_shader);
75 		if (!visual_shader->is_connected("changed", this, "_update_preview")) {
76 			visual_shader->connect("changed", this, "_update_preview");
77 		}
78 		visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE);
79 	} else {
80 		if (visual_shader.is_valid()) {
81 			if (visual_shader->is_connected("changed", this, "")) {
82 				visual_shader->disconnect("changed", this, "_update_preview");
83 			}
84 		}
85 		visual_shader.unref();
86 	}
87 
88 	if (visual_shader.is_null()) {
89 		hide();
90 	} else {
91 		if (changed) { // to avoid tree collapse
92 			_clear_buffer();
93 			_update_options_menu();
94 			_update_preview();
95 		}
96 		_update_graph();
97 	}
98 }
99 
add_plugin(const Ref<VisualShaderNodePlugin> & p_plugin)100 void VisualShaderEditor::add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
101 	if (plugins.find(p_plugin) != -1)
102 		return;
103 	plugins.push_back(p_plugin);
104 }
105 
remove_plugin(const Ref<VisualShaderNodePlugin> & p_plugin)106 void VisualShaderEditor::remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
107 	plugins.erase(p_plugin);
108 }
109 
clear_custom_types()110 void VisualShaderEditor::clear_custom_types() {
111 	for (int i = 0; i < add_options.size(); i++) {
112 		if (add_options[i].is_custom) {
113 			add_options.remove(i);
114 			i--;
115 		}
116 	}
117 }
118 
add_custom_type(const String & p_name,const Ref<Script> & p_script,const String & p_description,int p_return_icon_type,const String & p_category,const String & p_subcategory)119 void VisualShaderEditor::add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, const String &p_subcategory) {
120 
121 	ERR_FAIL_COND(!p_name.is_valid_identifier());
122 	ERR_FAIL_COND(!p_script.is_valid());
123 
124 	for (int i = 0; i < add_options.size(); i++) {
125 		if (add_options[i].is_custom) {
126 			if (add_options[i].script == p_script)
127 				return;
128 		}
129 	}
130 
131 	AddOption ao;
132 	ao.name = p_name;
133 	ao.script = p_script;
134 	ao.return_type = p_return_icon_type;
135 	ao.description = p_description;
136 	ao.category = p_category;
137 	ao.sub_category = p_subcategory;
138 	ao.is_custom = true;
139 
140 	bool begin = false;
141 
142 	for (int i = 0; i < add_options.size(); i++) {
143 		if (add_options[i].is_custom) {
144 			if (add_options[i].category == p_category) {
145 				if (!begin) {
146 					begin = true;
147 				}
148 			} else {
149 				if (begin) {
150 					add_options.insert(i, ao);
151 					return;
152 				}
153 			}
154 		}
155 	}
156 	add_options.push_back(ao);
157 }
158 
_is_available(int p_mode)159 bool VisualShaderEditor::_is_available(int p_mode) {
160 
161 	int current_mode = edit_type->get_selected();
162 
163 	if (p_mode != -1) {
164 
165 		switch (current_mode) {
166 			case VisualShader::TYPE_VERTEX:
167 				current_mode = 1;
168 				break;
169 			case VisualShader::TYPE_FRAGMENT:
170 				current_mode = 2;
171 				break;
172 			case VisualShader::TYPE_LIGHT:
173 				current_mode = 4;
174 				break;
175 			default:
176 				break;
177 		}
178 
179 		int temp_mode = 0;
180 
181 		if (p_mode & VisualShader::TYPE_FRAGMENT) {
182 			temp_mode |= 2;
183 		}
184 
185 		if (p_mode & VisualShader::TYPE_LIGHT) {
186 			temp_mode |= 4;
187 		}
188 
189 		if (temp_mode == 0) {
190 			temp_mode |= 1;
191 		}
192 
193 		p_mode = temp_mode;
194 	}
195 
196 	return (p_mode == -1 || (p_mode & current_mode) != 0);
197 }
198 
update_custom_nodes()199 void VisualShaderEditor::update_custom_nodes() {
200 	if (members_dialog->is_visible()) {
201 		return;
202 	}
203 	clear_custom_types();
204 	List<StringName> class_list;
205 	ScriptServer::get_global_class_list(&class_list);
206 	Dictionary added;
207 	for (int i = 0; i < class_list.size(); i++) {
208 		if (ScriptServer::get_global_class_native_base(class_list[i]) == "VisualShaderNodeCustom") {
209 
210 			String script_path = ScriptServer::get_global_class_path(class_list[i]);
211 			Ref<Resource> res = ResourceLoader::load(script_path);
212 			ERR_FAIL_COND(res.is_null());
213 			ERR_FAIL_COND(!res->is_class("Script"));
214 			Ref<Script> script = Ref<Script>(res);
215 
216 			Ref<VisualShaderNodeCustom> ref;
217 			ref.instance();
218 			ref->set_script(script.get_ref_ptr());
219 
220 			String name;
221 			if (ref->has_method("_get_name")) {
222 				name = (String)ref->call("_get_name");
223 			} else {
224 				name = "Unnamed";
225 			}
226 
227 			String description = "";
228 			if (ref->has_method("_get_description")) {
229 				description = (String)ref->call("_get_description");
230 			}
231 
232 			int return_icon_type = -1;
233 			if (ref->has_method("_get_return_icon_type")) {
234 				return_icon_type = (int)ref->call("_get_return_icon_type");
235 			}
236 
237 			String category = "";
238 			if (ref->has_method("_get_category")) {
239 				category = (String)ref->call("_get_category");
240 			}
241 			if (category == "") {
242 				category = "Custom";
243 			}
244 
245 			String subcategory = "";
246 			if (ref->has_method("_get_subcategory")) {
247 				subcategory = (String)ref->call("_get_subcategory");
248 			}
249 
250 			Dictionary dict;
251 			dict["name"] = name;
252 			dict["script"] = script;
253 			dict["description"] = description;
254 			dict["return_icon_type"] = return_icon_type;
255 			dict["category"] = category;
256 			dict["subcategory"] = subcategory;
257 
258 			String key;
259 			key = category;
260 			key += "/";
261 			if (subcategory != "") {
262 				key += subcategory;
263 				key += "/";
264 			}
265 			key += name;
266 
267 			added[key] = dict;
268 		}
269 	}
270 
271 	Array keys = added.keys();
272 	keys.sort();
273 
274 	for (int i = 0; i < keys.size(); i++) {
275 
276 		const Variant &key = keys.get(i);
277 
278 		const Dictionary &value = (Dictionary)added[key];
279 
280 		add_custom_type(value["name"], value["script"], value["description"], value["return_icon_type"], value["category"], value["subcategory"]);
281 	}
282 
283 	_update_options_menu();
284 }
285 
_get_description(int p_idx)286 String VisualShaderEditor::_get_description(int p_idx) {
287 	if (add_options[p_idx].highend) {
288 		return TTR("(GLES3 only)") + " " + add_options[p_idx].description; // TODO: change it to (Vulkan Only) when its ready
289 	} else {
290 		return add_options[p_idx].description;
291 	}
292 }
293 
_update_options_menu()294 void VisualShaderEditor::_update_options_menu() {
295 
296 	node_desc->set_text("");
297 	members_dialog->get_ok()->set_disabled(true);
298 
299 	String prev_category;
300 	String prev_sub_category;
301 
302 	members->clear();
303 	TreeItem *root = members->create_item();
304 	TreeItem *category = NULL;
305 	TreeItem *sub_category = NULL;
306 
307 	String filter = node_filter->get_text().strip_edges();
308 	bool use_filter = !filter.empty();
309 
310 	Vector<String> categories;
311 	Vector<String> sub_categories;
312 
313 	int item_count = 0;
314 	int item_count2 = 0;
315 	bool is_first_item = true;
316 
317 	Color unsupported_color = get_color("error_color", "Editor");
318 	Color supported_color = get_color("warning_color", "Editor");
319 
320 	static bool low_driver = ProjectSettings::get_singleton()->get("rendering/quality/driver/driver_name") == "GLES2";
321 
322 	int current_func = -1;
323 
324 	if (!visual_shader.is_null()) {
325 		current_func = visual_shader->get_mode();
326 	}
327 
328 	for (int i = 0; i < add_options.size() + 1; i++) {
329 
330 		if (i == add_options.size()) {
331 			if (sub_category != NULL && item_count2 == 0) {
332 				memdelete(sub_category);
333 				--item_count;
334 			}
335 			if (category != NULL && item_count == 0) {
336 				memdelete(category);
337 			}
338 			break;
339 		}
340 
341 		if (!use_filter || add_options[i].name.findn(filter) != -1) {
342 
343 			if ((add_options[i].func != current_func && add_options[i].func != -1) || !_is_available(add_options[i].mode))
344 				continue;
345 
346 			if (prev_category != add_options[i].category) {
347 				if (category != NULL && item_count == 0) {
348 					memdelete(category);
349 				}
350 
351 				item_count = 0;
352 				prev_sub_category = "";
353 				category = members->create_item(root);
354 				category->set_text(0, add_options[i].category);
355 				category->set_selectable(0, false);
356 				if (!use_filter)
357 					category->set_collapsed(true);
358 			}
359 
360 			if (add_options[i].sub_category != "") {
361 				if (prev_sub_category != add_options[i].sub_category) {
362 					if (category != NULL) {
363 						if (sub_category != NULL && item_count2 == 0) {
364 							memdelete(sub_category);
365 							--item_count;
366 						}
367 						++item_count;
368 						item_count2 = 0;
369 						sub_category = members->create_item(category);
370 						sub_category->set_text(0, add_options[i].sub_category);
371 						sub_category->set_selectable(0, false);
372 						if (!use_filter)
373 							sub_category->set_collapsed(true);
374 					}
375 				}
376 			} else {
377 				sub_category = NULL;
378 			}
379 
380 			TreeItem *p_category = NULL;
381 
382 			if (sub_category != NULL) {
383 				p_category = sub_category;
384 				++item_count2;
385 			} else if (category != NULL) {
386 				p_category = category;
387 				++item_count;
388 			}
389 
390 			if (p_category != NULL) {
391 				TreeItem *item = members->create_item(p_category);
392 				if (add_options[i].highend && low_driver)
393 					item->set_custom_color(0, unsupported_color);
394 				else if (add_options[i].highend)
395 					item->set_custom_color(0, supported_color);
396 				item->set_text(0, add_options[i].name);
397 				if (is_first_item && use_filter) {
398 					item->select(0);
399 					node_desc->set_text(_get_description(i));
400 					is_first_item = false;
401 				}
402 				switch (add_options[i].return_type) {
403 					case VisualShaderNode::PORT_TYPE_SCALAR:
404 						item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"));
405 						break;
406 					case VisualShaderNode::PORT_TYPE_VECTOR:
407 						item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons"));
408 						break;
409 					case VisualShaderNode::PORT_TYPE_BOOLEAN:
410 						item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons"));
411 						break;
412 					case VisualShaderNode::PORT_TYPE_TRANSFORM:
413 						item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"));
414 						break;
415 					case VisualShaderNode::PORT_TYPE_SAMPLER:
416 						item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons"));
417 						break;
418 					default:
419 						break;
420 				}
421 				item->set_meta("id", i);
422 			}
423 
424 			prev_sub_category = add_options[i].sub_category;
425 			prev_category = add_options[i].category;
426 		}
427 	}
428 }
429 
get_minimum_size() const430 Size2 VisualShaderEditor::get_minimum_size() const {
431 
432 	return Size2(10, 200);
433 }
434 
_draw_color_over_button(Object * obj,Color p_color)435 void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) {
436 
437 	Button *button = Object::cast_to<Button>(obj);
438 	if (!button)
439 		return;
440 
441 	Ref<StyleBox> normal = get_stylebox("normal", "Button");
442 	button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
443 }
444 
make_empty_stylebox(float p_margin_left=-1,float p_margin_top=-1,float p_margin_right=-1,float p_margin_bottom=-1)445 static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
446 	Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
447 	style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
448 	style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
449 	style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE);
450 	style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE);
451 	return style;
452 }
453 
_update_created_node(GraphNode * node)454 void VisualShaderEditor::_update_created_node(GraphNode *node) {
455 
456 	if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) {
457 		Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode");
458 		Color c = sb->get_border_color();
459 		Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0);
460 		mono_color.a = 0.85;
461 		c = mono_color;
462 
463 		node->add_color_override("title_color", c);
464 		c.a = 0.7;
465 		node->add_color_override("close_color", c);
466 		node->add_color_override("resizer_color", c);
467 	}
468 }
469 
_update_graph()470 void VisualShaderEditor::_update_graph() {
471 
472 	if (updating)
473 		return;
474 
475 	if (visual_shader.is_null())
476 		return;
477 
478 	graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE);
479 
480 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
481 	graph->clear_connections();
482 	//erase all nodes
483 	for (int i = 0; i < graph->get_child_count(); i++) {
484 
485 		if (Object::cast_to<GraphNode>(graph->get_child(i))) {
486 			Node *node = graph->get_child(i);
487 			graph->remove_child(node);
488 			memdelete(node);
489 			i--;
490 		}
491 	}
492 
493 	static const Color type_color[5] = {
494 		Color(0.38, 0.85, 0.96), // scalar
495 		Color(0.84, 0.49, 0.93), // vector
496 		Color(0.55, 0.65, 0.94), // boolean
497 		Color(0.96, 0.66, 0.43), // transform
498 		Color(1.0, 1.0, 0.0) // sampler
499 	};
500 
501 	List<VisualShader::Connection> connections;
502 	visual_shader->get_node_connections(type, &connections);
503 
504 	Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1);
505 
506 	Vector<int> nodes = visual_shader->get_node_list(type);
507 
508 	Control *offset;
509 
510 	for (int n_i = 0; n_i < nodes.size(); n_i++) {
511 
512 		Vector2 position = visual_shader->get_node_position(type, nodes[n_i]);
513 		Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]);
514 
515 		Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr());
516 		bool is_group = !group_node.is_null();
517 		Size2 size = Size2(0, 0);
518 
519 		Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr());
520 		bool is_expression = !expression_node.is_null();
521 		String expression = "";
522 
523 		GraphNode *node = memnew(GraphNode);
524 
525 		if (is_group) {
526 			size = group_node->get_size();
527 
528 			node->set_resizable(true);
529 			node->connect("resize_request", this, "_node_resized", varray((int)type, nodes[n_i]));
530 		}
531 		if (is_expression) {
532 			expression = expression_node->get_expression();
533 		}
534 
535 		/*if (!vsnode->is_connected("changed", this, "_node_changed")) {
536 			vsnode->connect("changed", this, "_node_changed", varray(vsnode->get_instance_id()), CONNECT_DEFERRED);
537 		}*/
538 
539 		node->set_offset(position);
540 
541 		node->set_title(vsnode->get_caption());
542 		node->set_name(itos(nodes[n_i]));
543 
544 		if (nodes[n_i] >= 2) {
545 			node->set_show_close_button(true);
546 			node->connect("close_request", this, "_delete_request", varray(nodes[n_i]), CONNECT_DEFERRED);
547 		}
548 
549 		node->connect("dragged", this, "_node_dragged", varray(nodes[n_i]));
550 
551 		Control *custom_editor = NULL;
552 		int port_offset = 0;
553 
554 		if (is_group) {
555 			port_offset += 2;
556 		}
557 
558 		Ref<VisualShaderNodeUniform> uniform = vsnode;
559 		if (uniform.is_valid()) {
560 			graph->add_child(node);
561 			_update_created_node(node);
562 
563 			LineEdit *uniform_name = memnew(LineEdit);
564 			uniform_name->set_text(uniform->get_uniform_name());
565 			node->add_child(uniform_name);
566 			uniform_name->connect("text_entered", this, "_line_edit_changed", varray(uniform_name, nodes[n_i]));
567 			uniform_name->connect("focus_exited", this, "_line_edit_focus_out", varray(uniform_name, nodes[n_i]));
568 
569 			if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
570 				//shortcut
571 				VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
572 				node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]);
573 				continue;
574 			}
575 			port_offset++;
576 		}
577 
578 		for (int i = 0; i < plugins.size(); i++) {
579 			custom_editor = plugins.write[i]->create_editor(visual_shader, vsnode);
580 			if (custom_editor) {
581 				break;
582 			}
583 		}
584 
585 		if (custom_editor && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) {
586 			//will be embedded in first port
587 		} else if (custom_editor) {
588 			port_offset++;
589 			node->add_child(custom_editor);
590 			custom_editor = NULL;
591 		}
592 
593 		if (is_group) {
594 
595 			offset = memnew(Control);
596 			offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE));
597 			node->add_child(offset);
598 
599 			if (group_node->is_editable()) {
600 				HBoxContainer *hb2 = memnew(HBoxContainer);
601 
602 				Button *add_input_btn = memnew(Button);
603 				add_input_btn->set_text(TTR("Add Input"));
604 				add_input_btn->connect("pressed", this, "_add_input_port", varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED);
605 				hb2->add_child(add_input_btn);
606 
607 				hb2->add_spacer();
608 
609 				Button *add_output_btn = memnew(Button);
610 				add_output_btn->set_text(TTR("Add Output"));
611 				add_output_btn->connect("pressed", this, "_add_output_port", varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED);
612 				hb2->add_child(add_output_btn);
613 
614 				node->add_child(hb2);
615 			}
616 		}
617 
618 		for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
619 
620 			if (vsnode->is_port_separator(i)) {
621 				node->add_child(memnew(HSeparator));
622 				port_offset++;
623 			}
624 
625 			bool valid_left = i < vsnode->get_input_port_count();
626 			VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR;
627 			bool port_left_used = false;
628 			String name_left;
629 			if (valid_left) {
630 				name_left = vsnode->get_input_port_name(i);
631 				port_left = vsnode->get_input_port_type(i);
632 				for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
633 					if (E->get().to_node == nodes[n_i] && E->get().to_port == i) {
634 						port_left_used = true;
635 					}
636 				}
637 			}
638 
639 			bool valid_right = i < vsnode->get_output_port_count();
640 			VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR;
641 			String name_right;
642 			if (valid_right) {
643 				name_right = vsnode->get_output_port_name(i);
644 				port_right = vsnode->get_output_port_type(i);
645 			}
646 
647 			HBoxContainer *hb = memnew(HBoxContainer);
648 			hb->add_constant_override("separation", 7 * EDSCALE);
649 
650 			Variant default_value;
651 
652 			if (valid_left && !port_left_used) {
653 				default_value = vsnode->get_input_port_default_value(i);
654 			}
655 
656 			if (default_value.get_type() != Variant::NIL) { // only a label
657 				Button *button = memnew(Button);
658 				hb->add_child(button);
659 				button->connect("pressed", this, "_edit_port_default_input", varray(button, nodes[n_i], i));
660 
661 				switch (default_value.get_type()) {
662 
663 					case Variant::COLOR: {
664 						button->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
665 						button->connect("draw", this, "_draw_color_over_button", varray(button, default_value));
666 					} break;
667 					case Variant::BOOL: {
668 						button->set_text(((bool)default_value) ? "true" : "false");
669 					} break;
670 					case Variant::INT:
671 					case Variant::REAL: {
672 						button->set_text(String::num(default_value, 4));
673 					} break;
674 					case Variant::VECTOR3: {
675 						Vector3 v = default_value;
676 						button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3));
677 					} break;
678 					default: {
679 					}
680 				}
681 			}
682 
683 			if (i == 0 && custom_editor) {
684 				hb->add_child(custom_editor);
685 				custom_editor->set_h_size_flags(SIZE_EXPAND_FILL);
686 			} else {
687 
688 				if (valid_left) {
689 
690 					if (is_group) {
691 						OptionButton *type_box = memnew(OptionButton);
692 						hb->add_child(type_box);
693 						type_box->add_item(TTR("Scalar"));
694 						type_box->add_item(TTR("Vector"));
695 						type_box->add_item(TTR("Boolean"));
696 						type_box->add_item(TTR("Transform"));
697 						type_box->add_item(TTR("Sampler"));
698 						type_box->select(group_node->get_input_port_type(i));
699 						type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
700 						type_box->connect("item_selected", this, "_change_input_port_type", varray(nodes[n_i], i), CONNECT_DEFERRED);
701 
702 						LineEdit *name_box = memnew(LineEdit);
703 						hb->add_child(name_box);
704 						name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
705 						name_box->set_h_size_flags(SIZE_EXPAND_FILL);
706 						name_box->set_text(name_left);
707 						name_box->connect("text_entered", this, "_change_input_port_name", varray(name_box, nodes[n_i], i));
708 						name_box->connect("focus_exited", this, "_port_name_focus_out", varray(name_box, nodes[n_i], i, false));
709 
710 						Button *remove_btn = memnew(Button);
711 						remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons"));
712 						remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
713 						remove_btn->connect("pressed", this, "_remove_input_port", varray(nodes[n_i], i), CONNECT_DEFERRED);
714 						hb->add_child(remove_btn);
715 					} else {
716 
717 						Label *label = memnew(Label);
718 						label->set_text(name_left);
719 						label->add_style_override("normal", label_style); //more compact
720 						hb->add_child(label);
721 
722 						if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) {
723 
724 							Label *hint_label = memnew(Label);
725 							hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]");
726 							hint_label->add_color_override("font_color", get_color("font_color_readonly", "TextEdit"));
727 							hint_label->add_style_override("normal", label_style);
728 							hb->add_child(hint_label);
729 						}
730 					}
731 				}
732 
733 				if (!is_group) {
734 					hb->add_spacer();
735 				}
736 
737 				if (valid_right) {
738 					if (is_group) {
739 						Button *remove_btn = memnew(Button);
740 						remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Remove", "EditorIcons"));
741 						remove_btn->set_tooltip(TTR("Remove") + " " + name_left);
742 						remove_btn->connect("pressed", this, "_remove_output_port", varray(nodes[n_i], i), CONNECT_DEFERRED);
743 						hb->add_child(remove_btn);
744 
745 						LineEdit *name_box = memnew(LineEdit);
746 						hb->add_child(name_box);
747 						name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
748 						name_box->set_h_size_flags(SIZE_EXPAND_FILL);
749 						name_box->set_text(name_right);
750 						name_box->connect("text_entered", this, "_change_output_port_name", varray(name_box, nodes[n_i], i));
751 						name_box->connect("focus_exited", this, "_port_name_focus_out", varray(name_box, nodes[n_i], i, true));
752 
753 						OptionButton *type_box = memnew(OptionButton);
754 						hb->add_child(type_box);
755 						type_box->add_item(TTR("Scalar"));
756 						type_box->add_item(TTR("Vector"));
757 						type_box->add_item(TTR("Boolean"));
758 						type_box->add_item(TTR("Transform"));
759 						type_box->select(group_node->get_output_port_type(i));
760 						type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
761 						type_box->connect("item_selected", this, "_change_output_port_type", varray(nodes[n_i], i), CONNECT_DEFERRED);
762 					} else {
763 						Label *label = memnew(Label);
764 						label->set_text(name_right);
765 						label->add_style_override("normal", label_style); //more compact
766 						hb->add_child(label);
767 					}
768 				}
769 			}
770 
771 			if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
772 				TextureButton *preview = memnew(TextureButton);
773 				preview->set_toggle_mode(true);
774 				preview->set_normal_texture(get_icon("GuiVisibilityHidden", "EditorIcons"));
775 				preview->set_pressed_texture(get_icon("GuiVisibilityVisible", "EditorIcons"));
776 				preview->set_v_size_flags(SIZE_SHRINK_CENTER);
777 
778 				if (vsnode->get_output_port_for_preview() == i) {
779 					preview->set_pressed(true);
780 				}
781 
782 				preview->connect("pressed", this, "_preview_select_port", varray(nodes[n_i], i), CONNECT_DEFERRED);
783 				hb->add_child(preview);
784 			}
785 
786 			if (is_group) {
787 				offset = memnew(Control);
788 				offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
789 				node->add_child(offset);
790 				port_offset++;
791 			}
792 
793 			node->add_child(hb);
794 
795 			node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
796 		}
797 
798 		if (vsnode->get_output_port_for_preview() >= 0) {
799 			int port_type = vsnode->get_output_port_type(vsnode->get_output_port_for_preview());
800 
801 			if (port_type != VisualShaderNode::PORT_TYPE_TRANSFORM && port_type != VisualShaderNode::PORT_TYPE_SAMPLER) {
802 				offset = memnew(Control);
803 				offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
804 				node->add_child(offset);
805 
806 				VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
807 				port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
808 				port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
809 				node->add_child(port_preview);
810 			}
811 		}
812 
813 		offset = memnew(Control);
814 		offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE));
815 		node->add_child(offset);
816 
817 		String error = vsnode->get_warning(visual_shader->get_mode(), type);
818 		if (error != String()) {
819 			Label *error_label = memnew(Label);
820 			error_label->add_color_override("font_color", get_color("error_color", "Editor"));
821 			error_label->set_text(error);
822 			node->add_child(error_label);
823 		}
824 
825 		if (is_expression) {
826 
827 			TextEdit *expression_box = memnew(TextEdit);
828 			expression_node->set_control(expression_box, 0);
829 			node->add_child(expression_box);
830 
831 			Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
832 			Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
833 			Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
834 			Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
835 			Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
836 
837 			expression_box->set_syntax_coloring(true);
838 			expression_box->add_color_override("background_color", background_color);
839 
840 			for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
841 
842 				expression_box->add_keyword_color(E->get(), keyword_color);
843 			}
844 
845 			expression_box->add_font_override("font", get_font("expression", "EditorFonts"));
846 			expression_box->add_color_override("font_color", text_color);
847 			expression_box->add_color_override("symbol_color", symbol_color);
848 			expression_box->add_color_region("/*", "*/", comment_color, false);
849 			expression_box->add_color_region("//", "", comment_color, false);
850 
851 			expression_box->set_text(expression);
852 			expression_box->set_context_menu_enabled(false);
853 			expression_box->set_show_line_numbers(true);
854 
855 			expression_box->connect("focus_exited", this, "_expression_focus_out", varray(expression_box, nodes[n_i]));
856 		}
857 
858 		if (!uniform.is_valid()) {
859 			graph->add_child(node);
860 			_update_created_node(node);
861 			if (is_group)
862 				call_deferred("_set_node_size", (int)type, nodes[n_i], size);
863 		}
864 	}
865 
866 	for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
867 
868 		int from = E->get().from_node;
869 		int from_idx = E->get().from_port;
870 		int to = E->get().to_node;
871 		int to_idx = E->get().to_port;
872 
873 		graph->connect_node(itos(from), from_idx, itos(to), to_idx);
874 	}
875 }
876 
_add_input_port(int p_node,int p_port,int p_port_type,const String & p_name)877 void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type, const String &p_name) {
878 
879 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
880 	Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
881 	if (node.is_null()) {
882 		return;
883 	}
884 
885 	undo_redo->create_action(TTR("Add input port"));
886 	undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
887 	undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
888 	undo_redo->add_do_method(this, "_update_graph");
889 	undo_redo->add_undo_method(this, "_update_graph");
890 	undo_redo->add_do_method(this, "_rebuild");
891 	undo_redo->add_undo_method(this, "_rebuild");
892 	undo_redo->commit_action();
893 }
894 
_add_output_port(int p_node,int p_port,int p_port_type,const String & p_name)895 void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_type, const String &p_name) {
896 
897 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
898 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
899 	if (node.is_null()) {
900 		return;
901 	}
902 
903 	undo_redo->create_action(TTR("Add output port"));
904 	undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
905 	undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
906 	undo_redo->add_do_method(this, "_update_graph");
907 	undo_redo->add_undo_method(this, "_update_graph");
908 	undo_redo->add_do_method(this, "_rebuild");
909 	undo_redo->add_undo_method(this, "_rebuild");
910 	undo_redo->commit_action();
911 }
912 
_change_input_port_type(int p_type,int p_node,int p_port)913 void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_port) {
914 
915 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
916 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
917 	if (node.is_null()) {
918 		return;
919 	}
920 
921 	undo_redo->create_action(TTR("Change input port type"));
922 	undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
923 	undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
924 	undo_redo->add_do_method(this, "_update_graph");
925 	undo_redo->add_undo_method(this, "_update_graph");
926 	undo_redo->add_do_method(this, "_rebuild");
927 	undo_redo->add_undo_method(this, "_rebuild");
928 	undo_redo->commit_action();
929 }
930 
_change_output_port_type(int p_type,int p_node,int p_port)931 void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_port) {
932 
933 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
934 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
935 	if (node.is_null()) {
936 		return;
937 	}
938 
939 	undo_redo->create_action(TTR("Change output port type"));
940 	undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
941 	undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
942 	undo_redo->add_do_method(this, "_update_graph");
943 	undo_redo->add_undo_method(this, "_update_graph");
944 	undo_redo->add_do_method(this, "_rebuild");
945 	undo_redo->add_undo_method(this, "_rebuild");
946 	undo_redo->commit_action();
947 }
948 
_change_input_port_name(const String & p_text,Object * line_edit,int p_node_id,int p_port_id)949 void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) {
950 
951 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
952 
953 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
954 	ERR_FAIL_COND(!node.is_valid());
955 
956 	undo_redo->create_action(TTR("Change input port name"));
957 	undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, p_text);
958 	undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
959 	undo_redo->add_do_method(this, "_rebuild");
960 	undo_redo->add_undo_method(this, "_rebuild");
961 	undo_redo->commit_action();
962 }
963 
_change_output_port_name(const String & p_text,Object * line_edit,int p_node_id,int p_port_id)964 void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) {
965 
966 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
967 
968 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
969 	ERR_FAIL_COND(!node.is_valid());
970 
971 	undo_redo->create_action(TTR("Change output port name"));
972 	undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, p_text);
973 	undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, node->get_output_port_name(p_port_id));
974 	undo_redo->add_do_method(this, "_rebuild");
975 	undo_redo->add_undo_method(this, "_rebuild");
976 	undo_redo->commit_action();
977 }
978 
_remove_input_port(int p_node,int p_port)979 void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
980 
981 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
982 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
983 	if (node.is_null()) {
984 		return;
985 	}
986 
987 	undo_redo->create_action(TTR("Remove input port"));
988 
989 	List<VisualShader::Connection> conns;
990 	visual_shader->get_node_connections(type, &conns);
991 	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
992 
993 		int from_node = E->get().from_node;
994 		int from_port = E->get().from_port;
995 		int to_node = E->get().to_node;
996 		int to_port = E->get().to_port;
997 
998 		if (to_node == p_node) {
999 			if (to_port == p_port) {
1000 				undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
1001 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
1002 			} else if (to_port > p_port) {
1003 				undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
1004 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
1005 
1006 				undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port - 1);
1007 				undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port - 1);
1008 			}
1009 		}
1010 	}
1011 
1012 	undo_redo->add_do_method(node.ptr(), "remove_input_port", p_port);
1013 	undo_redo->add_undo_method(node.ptr(), "add_input_port", p_port, (int)node->get_input_port_type(p_port), node->get_input_port_name(p_port));
1014 
1015 	undo_redo->add_do_method(this, "_update_graph");
1016 	undo_redo->add_undo_method(this, "_update_graph");
1017 
1018 	undo_redo->add_do_method(this, "_rebuild");
1019 	undo_redo->add_undo_method(this, "_rebuild");
1020 
1021 	undo_redo->commit_action();
1022 }
1023 
_remove_output_port(int p_node,int p_port)1024 void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
1025 
1026 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1027 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
1028 	if (node.is_null()) {
1029 		return;
1030 	}
1031 
1032 	undo_redo->create_action(TTR("Remove output port"));
1033 
1034 	List<VisualShader::Connection> conns;
1035 	visual_shader->get_node_connections(type, &conns);
1036 	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
1037 
1038 		int from_node = E->get().from_node;
1039 		int from_port = E->get().from_port;
1040 		int to_node = E->get().to_node;
1041 		int to_port = E->get().to_port;
1042 
1043 		if (from_node == p_node) {
1044 			if (from_port == p_port) {
1045 				undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
1046 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
1047 			} else if (from_port > p_port) {
1048 				undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
1049 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port, to_node, to_port);
1050 
1051 				undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, from_node, from_port - 1, to_node, to_port);
1052 				undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port - 1, to_node, to_port);
1053 			}
1054 		}
1055 	}
1056 
1057 	undo_redo->add_do_method(node.ptr(), "remove_output_port", p_port);
1058 	undo_redo->add_undo_method(node.ptr(), "add_output_port", p_port, (int)node->get_output_port_type(p_port), node->get_output_port_name(p_port));
1059 
1060 	undo_redo->add_do_method(this, "_update_graph");
1061 	undo_redo->add_undo_method(this, "_update_graph");
1062 
1063 	undo_redo->add_do_method(this, "_rebuild");
1064 	undo_redo->add_undo_method(this, "_rebuild");
1065 
1066 	undo_redo->commit_action();
1067 }
1068 
_expression_focus_out(Object * text_edit,int p_node)1069 void VisualShaderEditor::_expression_focus_out(Object *text_edit, int p_node) {
1070 
1071 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1072 	Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
1073 	if (node.is_null()) {
1074 		return;
1075 	}
1076 
1077 	TextEdit *expression_box = Object::cast_to<TextEdit>(text_edit);
1078 
1079 	if (node->get_expression() == expression_box->get_text())
1080 		return;
1081 
1082 	undo_redo->create_action(TTR("Set expression"));
1083 	undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
1084 	undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
1085 	undo_redo->add_do_method(this, "_rebuild");
1086 	undo_redo->add_undo_method(this, "_rebuild");
1087 	undo_redo->commit_action();
1088 }
1089 
_rebuild()1090 void VisualShaderEditor::_rebuild() {
1091 	if (visual_shader != NULL) {
1092 		EditorNode::get_singleton()->get_log()->clear();
1093 		visual_shader->rebuild();
1094 	}
1095 }
1096 
_set_node_size(int p_type,int p_node,const Vector2 & p_size)1097 void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) {
1098 
1099 	VisualShader::Type type = VisualShader::Type(p_type);
1100 	Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
1101 	if (node.is_null()) {
1102 		return;
1103 	}
1104 
1105 	Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
1106 
1107 	if (group_node.is_null()) {
1108 		return;
1109 	}
1110 
1111 	Vector2 size = p_size;
1112 
1113 	group_node->set_size(size);
1114 
1115 	GraphNode *gn = NULL;
1116 	if (edit_type->get_selected() == p_type) { // check - otherwise the error will be emitted
1117 		Node *node2 = graph->get_node(itos(p_node));
1118 		gn = Object::cast_to<GraphNode>(node2);
1119 		if (!gn)
1120 			return;
1121 
1122 		gn->set_custom_minimum_size(size);
1123 		gn->set_size(Size2(1, 1));
1124 	}
1125 
1126 	Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
1127 	if (!expression_node.is_null()) {
1128 		Control *text_box = expression_node->get_control(0);
1129 		Size2 box_size = size;
1130 		if (gn != NULL) {
1131 			if (box_size.x < 150 * EDSCALE || box_size.y < 0) {
1132 				box_size.x = gn->get_size().x;
1133 			}
1134 		}
1135 		box_size.x -= text_box->get_margin(MARGIN_LEFT);
1136 		box_size.x -= 28 * EDSCALE;
1137 		box_size.y -= text_box->get_margin(MARGIN_TOP);
1138 		box_size.y -= 28 * EDSCALE;
1139 		text_box->set_custom_minimum_size(Size2(box_size.x, box_size.y));
1140 		text_box->set_size(Size2(1, 1));
1141 	}
1142 }
1143 
_node_resized(const Vector2 & p_new_size,int p_type,int p_node)1144 void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) {
1145 
1146 	VisualShader::Type type = VisualShader::Type(p_type);
1147 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
1148 	if (node.is_null()) {
1149 		return;
1150 	}
1151 
1152 	undo_redo->create_action(TTR("Resize VisualShader node"), UndoRedo::MERGE_ENDS);
1153 	undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, p_new_size);
1154 	undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
1155 	undo_redo->commit_action();
1156 }
1157 
_preview_select_port(int p_node,int p_port)1158 void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
1159 
1160 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1161 	Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
1162 	if (node.is_null()) {
1163 		return;
1164 	}
1165 
1166 	if (node->get_output_port_for_preview() == p_port) {
1167 		p_port = -1; //toggle it
1168 	}
1169 	undo_redo->create_action(TTR("Set Uniform Name"));
1170 	undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port);
1171 	undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", node->get_output_port_for_preview());
1172 	undo_redo->add_do_method(this, "_update_graph");
1173 	undo_redo->add_undo_method(this, "_update_graph");
1174 	undo_redo->commit_action();
1175 }
1176 
_line_edit_changed(const String & p_text,Object * line_edit,int p_node_id)1177 void VisualShaderEditor::_line_edit_changed(const String &p_text, Object *line_edit, int p_node_id) {
1178 
1179 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1180 
1181 	Ref<VisualShaderNodeUniform> node = visual_shader->get_node(type, p_node_id);
1182 	ERR_FAIL_COND(!node.is_valid());
1183 
1184 	String validated_name = visual_shader->validate_uniform_name(p_text, node);
1185 
1186 	updating = true;
1187 	undo_redo->create_action(TTR("Set Uniform Name"));
1188 	undo_redo->add_do_method(node.ptr(), "set_uniform_name", validated_name);
1189 	undo_redo->add_undo_method(node.ptr(), "set_uniform_name", node->get_uniform_name());
1190 	undo_redo->add_do_method(this, "_update_graph");
1191 	undo_redo->add_undo_method(this, "_update_graph");
1192 	undo_redo->commit_action();
1193 	updating = false;
1194 
1195 	Object::cast_to<LineEdit>(line_edit)->set_text(validated_name);
1196 }
1197 
_line_edit_focus_out(Object * line_edit,int p_node_id)1198 void VisualShaderEditor::_line_edit_focus_out(Object *line_edit, int p_node_id) {
1199 
1200 	String text = Object::cast_to<LineEdit>(line_edit)->get_text();
1201 	_line_edit_changed(text, line_edit, p_node_id);
1202 }
1203 
_port_name_focus_out(Object * line_edit,int p_node_id,int p_port_id,bool p_output)1204 void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) {
1205 
1206 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1207 
1208 	Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
1209 	ERR_FAIL_COND(!node.is_valid());
1210 
1211 	String text = Object::cast_to<LineEdit>(line_edit)->get_text();
1212 
1213 	if (!p_output) {
1214 		if (node->get_input_port_name(p_port_id) == text)
1215 			return;
1216 	} else {
1217 		if (node->get_output_port_name(p_port_id) == text)
1218 			return;
1219 	}
1220 
1221 	List<String> input_names;
1222 	List<String> output_names;
1223 
1224 	for (int i = 0; i < node->get_input_port_count(); i++) {
1225 		if (!p_output && i == p_port_id) continue;
1226 		input_names.push_back(node->get_input_port_name(i));
1227 	}
1228 	for (int i = 0; i < node->get_output_port_count(); i++) {
1229 		if (p_output && i == p_port_id) continue;
1230 		output_names.push_back(node->get_output_port_name(i));
1231 	}
1232 
1233 	String validated_name = visual_shader->validate_port_name(text, input_names, output_names);
1234 	if (validated_name == "") {
1235 		if (!p_output) {
1236 			Object::cast_to<LineEdit>(line_edit)->set_text(node->get_input_port_name(p_port_id));
1237 		} else {
1238 			Object::cast_to<LineEdit>(line_edit)->set_text(node->get_output_port_name(p_port_id));
1239 		}
1240 		return;
1241 	}
1242 
1243 	if (!p_output) {
1244 		_change_input_port_name(validated_name, line_edit, p_node_id, p_port_id);
1245 	} else {
1246 		_change_output_port_name(validated_name, line_edit, p_node_id, p_port_id);
1247 	}
1248 }
1249 
_port_edited()1250 void VisualShaderEditor::_port_edited() {
1251 
1252 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1253 
1254 	Variant value = property_editor->get_variant();
1255 	Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node);
1256 	ERR_FAIL_COND(!vsn.is_valid());
1257 
1258 	undo_redo->create_action(TTR("Set Input Default Port"));
1259 	undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value);
1260 	undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
1261 	undo_redo->add_do_method(this, "_update_graph");
1262 	undo_redo->add_undo_method(this, "_update_graph");
1263 	undo_redo->commit_action();
1264 
1265 	property_editor->hide();
1266 }
1267 
_edit_port_default_input(Object * p_button,int p_node,int p_port)1268 void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) {
1269 
1270 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1271 
1272 	Ref<VisualShaderNode> vsn = visual_shader->get_node(type, p_node);
1273 
1274 	Button *button = Object::cast_to<Button>(p_button);
1275 	ERR_FAIL_COND(!button);
1276 	Variant value = vsn->get_input_port_default_value(p_port);
1277 	property_editor->set_global_position(button->get_global_position() + Vector2(0, button->get_size().height));
1278 	property_editor->edit(NULL, "", value.get_type(), value, 0, "");
1279 	property_editor->popup();
1280 	editing_node = p_node;
1281 	editing_port = p_port;
1282 }
1283 
_add_custom_node(const String & p_path)1284 void VisualShaderEditor::_add_custom_node(const String &p_path) {
1285 
1286 	int idx = -1;
1287 
1288 	for (int i = custom_node_option_idx; i < add_options.size(); i++) {
1289 		if (add_options[i].script.is_valid()) {
1290 			if (add_options[i].script->get_path() == p_path) {
1291 				idx = i;
1292 				break;
1293 			}
1294 		}
1295 	}
1296 	if (idx != -1) {
1297 		_add_node(idx);
1298 	}
1299 }
1300 
_add_texture_node(const String & p_path)1301 void VisualShaderEditor::_add_texture_node(const String &p_path) {
1302 	VisualShaderNodeTexture *texture = (VisualShaderNodeTexture *)_add_node(texture_node_option_idx, -1);
1303 	texture->set_texture(ResourceLoader::load(p_path));
1304 }
1305 
_add_node(int p_idx,int p_op_idx)1306 VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
1307 
1308 	ERR_FAIL_INDEX_V(p_idx, add_options.size(), NULL);
1309 
1310 	Ref<VisualShaderNode> vsnode;
1311 
1312 	bool is_custom = add_options[p_idx].is_custom;
1313 
1314 	if (!is_custom && add_options[p_idx].type != String()) {
1315 		VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(add_options[p_idx].type));
1316 		ERR_FAIL_COND_V(!vsn, NULL);
1317 
1318 		VisualShaderNodeScalarConstant *constant = Object::cast_to<VisualShaderNodeScalarConstant>(vsn);
1319 
1320 		if (constant) {
1321 			if ((int)add_options[p_idx].value != -1)
1322 				constant->set_constant(add_options[p_idx].value);
1323 		}
1324 
1325 		if (p_op_idx != -1) {
1326 
1327 			VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsn);
1328 
1329 			if (input) {
1330 				input->set_input_name(add_options[p_idx].sub_func_str);
1331 			}
1332 
1333 			VisualShaderNodeIs *is = Object::cast_to<VisualShaderNodeIs>(vsn);
1334 
1335 			if (is) {
1336 				is->set_function((VisualShaderNodeIs::Function)p_op_idx);
1337 			}
1338 
1339 			VisualShaderNodeCompare *cmp = Object::cast_to<VisualShaderNodeCompare>(vsn);
1340 
1341 			if (cmp) {
1342 				cmp->set_function((VisualShaderNodeCompare::Function)p_op_idx);
1343 			}
1344 
1345 			VisualShaderNodeColorOp *colorOp = Object::cast_to<VisualShaderNodeColorOp>(vsn);
1346 
1347 			if (colorOp) {
1348 				colorOp->set_operator((VisualShaderNodeColorOp::Operator)p_op_idx);
1349 			}
1350 
1351 			VisualShaderNodeColorFunc *colorFunc = Object::cast_to<VisualShaderNodeColorFunc>(vsn);
1352 
1353 			if (colorFunc) {
1354 				colorFunc->set_function((VisualShaderNodeColorFunc::Function)p_op_idx);
1355 			}
1356 
1357 			VisualShaderNodeScalarOp *scalarOp = Object::cast_to<VisualShaderNodeScalarOp>(vsn);
1358 
1359 			if (scalarOp) {
1360 				scalarOp->set_operator((VisualShaderNodeScalarOp::Operator)p_op_idx);
1361 			}
1362 
1363 			VisualShaderNodeScalarFunc *scalarFunc = Object::cast_to<VisualShaderNodeScalarFunc>(vsn);
1364 
1365 			if (scalarFunc) {
1366 				scalarFunc->set_function((VisualShaderNodeScalarFunc::Function)p_op_idx);
1367 			}
1368 
1369 			VisualShaderNodeVectorOp *vecOp = Object::cast_to<VisualShaderNodeVectorOp>(vsn);
1370 
1371 			if (vecOp) {
1372 				vecOp->set_operator((VisualShaderNodeVectorOp::Operator)p_op_idx);
1373 			}
1374 
1375 			VisualShaderNodeVectorFunc *vecFunc = Object::cast_to<VisualShaderNodeVectorFunc>(vsn);
1376 
1377 			if (vecFunc) {
1378 				vecFunc->set_function((VisualShaderNodeVectorFunc::Function)p_op_idx);
1379 			}
1380 
1381 			VisualShaderNodeTransformFunc *matFunc = Object::cast_to<VisualShaderNodeTransformFunc>(vsn);
1382 
1383 			if (matFunc) {
1384 				matFunc->set_function((VisualShaderNodeTransformFunc::Function)p_op_idx);
1385 			}
1386 
1387 			VisualShaderNodeScalarDerivativeFunc *sderFunc = Object::cast_to<VisualShaderNodeScalarDerivativeFunc>(vsn);
1388 
1389 			if (sderFunc) {
1390 				sderFunc->set_function((VisualShaderNodeScalarDerivativeFunc::Function)p_op_idx);
1391 			}
1392 
1393 			VisualShaderNodeVectorDerivativeFunc *vderFunc = Object::cast_to<VisualShaderNodeVectorDerivativeFunc>(vsn);
1394 
1395 			if (vderFunc) {
1396 				vderFunc->set_function((VisualShaderNodeVectorDerivativeFunc::Function)p_op_idx);
1397 			}
1398 		}
1399 
1400 		vsnode = Ref<VisualShaderNode>(vsn);
1401 	} else {
1402 		ERR_FAIL_COND_V(add_options[p_idx].script.is_null(), NULL);
1403 		String base_type = add_options[p_idx].script->get_instance_base_type();
1404 		VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(base_type));
1405 		ERR_FAIL_COND_V(!vsn, NULL);
1406 		vsnode = Ref<VisualShaderNode>(vsn);
1407 		vsnode->set_script(add_options[p_idx].script.get_ref_ptr());
1408 	}
1409 
1410 	Point2 position = graph->get_scroll_ofs();
1411 
1412 	if (saved_node_pos_dirty) {
1413 		position += saved_node_pos;
1414 	} else {
1415 		position += graph->get_size() * 0.5;
1416 		position /= EDSCALE;
1417 	}
1418 	saved_node_pos_dirty = false;
1419 
1420 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1421 
1422 	int id_to_use = visual_shader->get_valid_node_id(type);
1423 
1424 	undo_redo->create_action(TTR("Add Node to Visual Shader"));
1425 	undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
1426 	undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
1427 
1428 	VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr());
1429 	if (expr) {
1430 		undo_redo->add_do_method(expr, "set_size", Size2(250 * EDSCALE, 150 * EDSCALE));
1431 	}
1432 
1433 	if (to_node != -1 && to_slot != -1) {
1434 		if (vsnode->get_output_port_count() > 0) {
1435 
1436 			int _from_node = id_to_use;
1437 			int _from_slot = 0;
1438 
1439 			if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(_from_slot), visual_shader->get_node(type, to_node)->get_input_port_type(to_slot))) {
1440 				undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
1441 				undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
1442 			}
1443 		}
1444 	} else if (from_node != -1 && from_slot != -1) {
1445 		if (vsnode->get_input_port_count() > 0) {
1446 
1447 			int _to_node = id_to_use;
1448 			int _to_slot = 0;
1449 
1450 			if (visual_shader->is_port_types_compatible(visual_shader->get_node(type, from_node)->get_output_port_type(from_slot), vsnode->get_input_port_type(_to_slot))) {
1451 				undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
1452 				undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
1453 			}
1454 		}
1455 	}
1456 
1457 	undo_redo->add_do_method(this, "_update_graph");
1458 	undo_redo->add_undo_method(this, "_update_graph");
1459 	undo_redo->commit_action();
1460 	return vsnode.ptr();
1461 }
1462 
_node_dragged(const Vector2 & p_from,const Vector2 & p_to,int p_node)1463 void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
1464 
1465 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1466 
1467 	updating = true;
1468 	undo_redo->create_action(TTR("Node Moved"));
1469 	undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", type, p_node, p_to);
1470 	undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", type, p_node, p_from);
1471 	undo_redo->add_do_method(this, "_update_graph");
1472 	undo_redo->add_undo_method(this, "_update_graph");
1473 	undo_redo->commit_action();
1474 	updating = false;
1475 }
1476 
_connection_request(const String & p_from,int p_from_index,const String & p_to,int p_to_index)1477 void VisualShaderEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
1478 
1479 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1480 
1481 	int from = p_from.to_int();
1482 	int to = p_to.to_int();
1483 
1484 	if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) {
1485 		return;
1486 	}
1487 
1488 	undo_redo->create_action(TTR("Nodes Connected"));
1489 
1490 	List<VisualShader::Connection> conns;
1491 	visual_shader->get_node_connections(type, &conns);
1492 
1493 	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
1494 		if (E->get().to_node == to && E->get().to_port == p_to_index) {
1495 			undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
1496 			undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
1497 		}
1498 	}
1499 
1500 	undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
1501 	undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
1502 	undo_redo->add_do_method(this, "_update_graph");
1503 	undo_redo->add_undo_method(this, "_update_graph");
1504 	undo_redo->commit_action();
1505 }
1506 
_disconnection_request(const String & p_from,int p_from_index,const String & p_to,int p_to_index)1507 void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
1508 
1509 	graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
1510 
1511 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1512 
1513 	int from = p_from.to_int();
1514 	int to = p_to.to_int();
1515 
1516 	//updating = true; seems graph edit can handle this, no need to protect
1517 	undo_redo->create_action(TTR("Nodes Disconnected"));
1518 	undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
1519 	undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
1520 	undo_redo->add_do_method(this, "_update_graph");
1521 	undo_redo->add_undo_method(this, "_update_graph");
1522 	undo_redo->commit_action();
1523 	//updating = false;
1524 }
1525 
_connection_to_empty(const String & p_from,int p_from_slot,const Vector2 & p_release_position)1526 void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
1527 	from_node = p_from.to_int();
1528 	from_slot = p_from_slot;
1529 	_show_members_dialog(true);
1530 }
1531 
_connection_from_empty(const String & p_to,int p_to_slot,const Vector2 & p_release_position)1532 void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) {
1533 	to_node = p_to.to_int();
1534 	to_slot = p_to_slot;
1535 	_show_members_dialog(true);
1536 }
1537 
_delete_request(int which)1538 void VisualShaderEditor::_delete_request(int which) {
1539 
1540 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1541 	Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which));
1542 
1543 	undo_redo->create_action(TTR("Delete Node"));
1544 	undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which);
1545 	undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which);
1546 
1547 	undo_redo->add_do_method(this, "_clear_buffer");
1548 	undo_redo->add_undo_method(this, "_clear_buffer");
1549 
1550 	// restore size, inputs and outputs if node is group
1551 	VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
1552 	if (group) {
1553 		undo_redo->add_undo_method(group, "set_size", group->get_size());
1554 		undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
1555 		undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
1556 	}
1557 
1558 	// restore expression text if node is expression
1559 	VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
1560 	if (expression) {
1561 		undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
1562 	}
1563 
1564 	List<VisualShader::Connection> conns;
1565 	visual_shader->get_node_connections(type, &conns);
1566 
1567 	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
1568 		if (E->get().from_node == which || E->get().to_node == which) {
1569 			undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
1570 		}
1571 	}
1572 
1573 	undo_redo->add_do_method(this, "_update_graph");
1574 	undo_redo->add_undo_method(this, "_update_graph");
1575 	undo_redo->commit_action();
1576 }
1577 
_node_selected(Object * p_node)1578 void VisualShaderEditor::_node_selected(Object *p_node) {
1579 
1580 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1581 
1582 	GraphNode *gn = Object::cast_to<GraphNode>(p_node);
1583 	ERR_FAIL_COND(!gn);
1584 
1585 	int id = String(gn->get_name()).to_int();
1586 
1587 	Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
1588 	ERR_FAIL_COND(!vsnode.is_valid());
1589 
1590 	//do not rely on this, makes editor more complex
1591 	//EditorNode::get_singleton()->push_item(vsnode.ptr(), "", true);
1592 }
1593 
_graph_gui_input(const Ref<InputEvent> & p_event)1594 void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
1595 
1596 	Ref<InputEventMouseButton> mb = p_event;
1597 
1598 	if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT)
1599 		_show_members_dialog(true);
1600 }
1601 
_show_members_dialog(bool at_mouse_pos)1602 void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
1603 
1604 	if (at_mouse_pos) {
1605 		saved_node_pos_dirty = true;
1606 		saved_node_pos = graph->get_local_mouse_position();
1607 
1608 		Point2 gpos = Input::get_singleton()->get_mouse_position();
1609 		members_dialog->popup();
1610 		members_dialog->set_position(gpos);
1611 	} else {
1612 		members_dialog->popup();
1613 		saved_node_pos_dirty = false;
1614 		members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
1615 	}
1616 
1617 	// keep dialog within window bounds
1618 	Size2 window_size = OS::get_singleton()->get_window_size();
1619 	Rect2 dialog_rect = members_dialog->get_global_rect();
1620 	if (dialog_rect.position.y + dialog_rect.size.y > window_size.y) {
1621 		int difference = dialog_rect.position.y + dialog_rect.size.y - window_size.y;
1622 		members_dialog->set_position(members_dialog->get_position() - Point2(0, difference));
1623 	}
1624 	if (dialog_rect.position.x + dialog_rect.size.x > window_size.x) {
1625 		int difference = dialog_rect.position.x + dialog_rect.size.x - window_size.x;
1626 		members_dialog->set_position(members_dialog->get_position() - Point2(difference, 0));
1627 	}
1628 
1629 	node_filter->call_deferred("grab_focus"); // still not visible
1630 	node_filter->select_all();
1631 }
1632 
_sbox_input(const Ref<InputEvent> & p_ie)1633 void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
1634 	Ref<InputEventKey> ie = p_ie;
1635 	if (ie.is_valid() && (ie->get_scancode() == KEY_UP ||
1636 								 ie->get_scancode() == KEY_DOWN ||
1637 								 ie->get_scancode() == KEY_ENTER ||
1638 								 ie->get_scancode() == KEY_KP_ENTER)) {
1639 
1640 		members->call("_gui_input", ie);
1641 		node_filter->accept_event();
1642 	}
1643 }
1644 
_notification(int p_what)1645 void VisualShaderEditor::_notification(int p_what) {
1646 	if (p_what == NOTIFICATION_ENTER_TREE) {
1647 
1648 		node_filter->set_clear_button_enabled(true);
1649 
1650 		// collapse tree by default
1651 
1652 		TreeItem *category = members->get_root()->get_children();
1653 		while (category) {
1654 			category->set_collapsed(true);
1655 			TreeItem *sub_category = category->get_children();
1656 			while (sub_category) {
1657 				sub_category->set_collapsed(true);
1658 				sub_category = sub_category->get_next();
1659 			}
1660 			category = category->get_next();
1661 		}
1662 	}
1663 
1664 	if (p_what == NOTIFICATION_DRAG_BEGIN) {
1665 		Dictionary dd = get_viewport()->gui_get_drag_data();
1666 		if (members->is_visible_in_tree() && dd.has("id")) {
1667 			members->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
1668 		}
1669 	} else if (p_what == NOTIFICATION_DRAG_END) {
1670 		members->set_drop_mode_flags(0);
1671 	}
1672 
1673 	if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
1674 
1675 		error_panel->add_style_override("panel", get_stylebox("bg", "Tree"));
1676 		error_label->add_color_override("font_color", get_color("error_color", "Editor"));
1677 
1678 		node_filter->set_right_icon(Control::get_icon("Search", "EditorIcons"));
1679 
1680 		preview_shader->set_icon(Control::get_icon("Shader", "EditorIcons"));
1681 
1682 		{
1683 			Color background_color = EDITOR_GET("text_editor/highlighting/background_color");
1684 			Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
1685 			Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
1686 			Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
1687 			Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color");
1688 
1689 			preview_text->add_color_override("background_color", background_color);
1690 
1691 			for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
1692 
1693 				preview_text->add_keyword_color(E->get(), keyword_color);
1694 			}
1695 
1696 			preview_text->add_font_override("font", get_font("expression", "EditorFonts"));
1697 			preview_text->add_color_override("font_color", text_color);
1698 			preview_text->add_color_override("symbol_color", symbol_color);
1699 			preview_text->add_color_region("/*", "*/", comment_color, false);
1700 			preview_text->add_color_region("//", "", comment_color, false);
1701 
1702 			error_text->add_font_override("font", get_font("status_source", "EditorFonts"));
1703 			error_text->add_color_override("font_color", get_color("error_color", "Editor"));
1704 		}
1705 
1706 		tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("Tools", "EditorIcons"));
1707 
1708 		if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree())
1709 			_update_graph();
1710 	}
1711 }
1712 
_scroll_changed(const Vector2 & p_scroll)1713 void VisualShaderEditor::_scroll_changed(const Vector2 &p_scroll) {
1714 	if (updating)
1715 		return;
1716 	updating = true;
1717 	visual_shader->set_graph_offset(p_scroll / EDSCALE);
1718 	updating = false;
1719 }
1720 
_node_changed(int p_id)1721 void VisualShaderEditor::_node_changed(int p_id) {
1722 	if (updating)
1723 		return;
1724 
1725 	if (is_visible_in_tree()) {
1726 		_update_graph();
1727 	}
1728 }
1729 
_dup_update_excluded(int p_type,Set<int> & r_excluded)1730 void VisualShaderEditor::_dup_update_excluded(int p_type, Set<int> &r_excluded) {
1731 	r_excluded.clear();
1732 	VisualShader::Type type = (VisualShader::Type)p_type;
1733 
1734 	for (int i = 0; i < graph->get_child_count(); i++) {
1735 
1736 		GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
1737 		if (gn) {
1738 			int id = String(gn->get_name()).to_int();
1739 			Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
1740 			Ref<VisualShaderNodeOutput> output = node;
1741 			if (output.is_valid()) {
1742 				r_excluded.insert(id);
1743 				continue;
1744 			}
1745 			r_excluded.insert(id);
1746 		}
1747 	}
1748 }
1749 
_dup_copy_nodes(int p_type,List<int> & r_nodes,Set<int> & r_excluded)1750 void VisualShaderEditor::_dup_copy_nodes(int p_type, List<int> &r_nodes, Set<int> &r_excluded) {
1751 
1752 	VisualShader::Type type = (VisualShader::Type)p_type;
1753 
1754 	selection_center.x = 0.0f;
1755 	selection_center.y = 0.0f;
1756 
1757 	for (int i = 0; i < graph->get_child_count(); i++) {
1758 
1759 		GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
1760 		if (gn) {
1761 			int id = String(gn->get_name()).to_int();
1762 			Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
1763 			Ref<VisualShaderNodeOutput> output = node;
1764 			if (output.is_valid()) { // can't duplicate output
1765 				r_excluded.insert(id);
1766 				continue;
1767 			}
1768 			if (node.is_valid() && gn->is_selected()) {
1769 				Vector2 pos = visual_shader->get_node_position(type, id);
1770 				selection_center += pos;
1771 				r_nodes.push_back(id);
1772 			}
1773 			r_excluded.insert(id);
1774 		}
1775 	}
1776 
1777 	selection_center /= (float)r_nodes.size();
1778 }
1779 
_dup_paste_nodes(int p_type,int p_pasted_type,List<int> & r_nodes,Set<int> & r_excluded,const Vector2 & p_offset,bool p_select)1780 void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<int> &r_nodes, Set<int> &r_excluded, const Vector2 &p_offset, bool p_select) {
1781 
1782 	VisualShader::Type type = (VisualShader::Type)p_type;
1783 	VisualShader::Type pasted_type = (VisualShader::Type)p_pasted_type;
1784 
1785 	int base_id = visual_shader->get_valid_node_id(type);
1786 	int id_from = base_id;
1787 	Map<int, int> connection_remap;
1788 	Set<int> unsupported_set;
1789 
1790 	for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) {
1791 
1792 		connection_remap[E->get()] = id_from;
1793 		Ref<VisualShaderNode> node = visual_shader->get_node(pasted_type, E->get());
1794 
1795 		bool unsupported = false;
1796 		for (int i = 0; i < add_options.size(); i++) {
1797 			if (add_options[i].type == node->get_class_name()) {
1798 				if (!_is_available(add_options[i].mode)) {
1799 					unsupported = true;
1800 				}
1801 				break;
1802 			}
1803 		}
1804 		if (unsupported) {
1805 			unsupported_set.insert(E->get());
1806 			continue;
1807 		}
1808 
1809 		Ref<VisualShaderNode> dupli = node->duplicate();
1810 
1811 		undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E->get()) + p_offset, id_from);
1812 		undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
1813 
1814 		// duplicate size, inputs and outputs if node is group
1815 		Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
1816 		if (!group.is_null()) {
1817 			undo_redo->add_do_method(dupli.ptr(), "set_size", group->get_size());
1818 			undo_redo->add_do_method(dupli.ptr(), "set_inputs", group->get_inputs());
1819 			undo_redo->add_do_method(dupli.ptr(), "set_outputs", group->get_outputs());
1820 		}
1821 		// duplicate expression text if node is expression
1822 		Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
1823 		if (!expression.is_null()) {
1824 			undo_redo->add_do_method(dupli.ptr(), "set_expression", expression->get_expression());
1825 		}
1826 
1827 		id_from++;
1828 	}
1829 
1830 	List<VisualShader::Connection> conns;
1831 	visual_shader->get_node_connections(pasted_type, &conns);
1832 
1833 	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
1834 		if (unsupported_set.has(E->get().from_node) || unsupported_set.has(E->get().to_node)) {
1835 			continue;
1836 		}
1837 		if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) {
1838 			undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
1839 		}
1840 	}
1841 
1842 	undo_redo->add_do_method(this, "_update_graph");
1843 	undo_redo->add_undo_method(this, "_update_graph");
1844 	undo_redo->commit_action();
1845 
1846 	if (p_select) {
1847 		// reselect duplicated nodes by excluding the other ones
1848 		for (int i = 0; i < graph->get_child_count(); i++) {
1849 
1850 			GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
1851 			if (gn) {
1852 				int id = String(gn->get_name()).to_int();
1853 				if (!r_excluded.has(id)) {
1854 					gn->set_selected(true);
1855 				} else {
1856 					gn->set_selected(false);
1857 				}
1858 			}
1859 		}
1860 	}
1861 }
1862 
_clear_buffer()1863 void VisualShaderEditor::_clear_buffer() {
1864 
1865 	copy_nodes_buffer.clear();
1866 	copy_nodes_excluded_buffer.clear();
1867 }
1868 
_duplicate_nodes()1869 void VisualShaderEditor::_duplicate_nodes() {
1870 
1871 	int type = edit_type->get_selected();
1872 
1873 	List<int> nodes;
1874 	Set<int> excluded;
1875 
1876 	_dup_copy_nodes(type, nodes, excluded);
1877 
1878 	if (nodes.empty())
1879 		return;
1880 
1881 	undo_redo->create_action(TTR("Duplicate Nodes"));
1882 
1883 	_dup_paste_nodes(type, type, nodes, excluded, Vector2(10, 10) * EDSCALE, true);
1884 }
1885 
_copy_nodes()1886 void VisualShaderEditor::_copy_nodes() {
1887 
1888 	copy_type = edit_type->get_selected();
1889 
1890 	_clear_buffer();
1891 
1892 	_dup_copy_nodes(copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer);
1893 }
1894 
_paste_nodes()1895 void VisualShaderEditor::_paste_nodes() {
1896 
1897 	if (copy_nodes_buffer.empty())
1898 		return;
1899 
1900 	int type = edit_type->get_selected();
1901 
1902 	undo_redo->create_action(TTR("Paste Nodes"));
1903 
1904 	float scale = graph->get_zoom();
1905 
1906 	_dup_paste_nodes(type, copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer, (graph->get_scroll_ofs() / scale + graph->get_local_mouse_position() / scale - selection_center), false);
1907 
1908 	_dup_update_excluded(type, copy_nodes_excluded_buffer); // to prevent selection of previous copies at new paste
1909 }
1910 
_on_nodes_delete()1911 void VisualShaderEditor::_on_nodes_delete() {
1912 
1913 	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
1914 	List<int> to_erase;
1915 
1916 	for (int i = 0; i < graph->get_child_count(); i++) {
1917 		GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
1918 		if (gn) {
1919 			if (gn->is_selected() && gn->is_close_button_visible()) {
1920 				to_erase.push_back(gn->get_name().operator String().to_int());
1921 			}
1922 		}
1923 	}
1924 
1925 	if (to_erase.empty())
1926 		return;
1927 
1928 	undo_redo->create_action(TTR("Delete Nodes"));
1929 
1930 	for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
1931 
1932 		Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get());
1933 
1934 		undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
1935 		undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get());
1936 
1937 		undo_redo->add_do_method(this, "_clear_buffer");
1938 		undo_redo->add_undo_method(this, "_clear_buffer");
1939 
1940 		// restore size, inputs and outputs if node is group
1941 		VisualShaderNodeGroupBase *group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
1942 		if (group) {
1943 			undo_redo->add_undo_method(group, "set_size", group->get_size());
1944 			undo_redo->add_undo_method(group, "set_inputs", group->get_inputs());
1945 			undo_redo->add_undo_method(group, "set_outputs", group->get_outputs());
1946 		}
1947 
1948 		// restore expression text if node is expression
1949 		VisualShaderNodeExpression *expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
1950 		if (expression) {
1951 			undo_redo->add_undo_method(expression, "set_expression", expression->get_expression());
1952 		}
1953 	}
1954 
1955 	List<VisualShader::Connection> conns;
1956 	visual_shader->get_node_connections(type, &conns);
1957 
1958 	List<VisualShader::Connection> used_conns;
1959 	for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
1960 		for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
1961 			if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
1962 
1963 				bool cancel = false;
1964 				for (List<VisualShader::Connection>::Element *R = used_conns.front(); R; R = R->next()) {
1965 					if (R->get().from_node == E->get().from_node && R->get().from_port == E->get().from_port && R->get().to_node == E->get().to_node && R->get().to_port == E->get().to_port) {
1966 						cancel = true; // to avoid ERR_ALREADY_EXISTS warning
1967 						break;
1968 					}
1969 				}
1970 				if (!cancel) {
1971 					undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
1972 					used_conns.push_back(E->get());
1973 				}
1974 			}
1975 		}
1976 	}
1977 
1978 	undo_redo->add_do_method(this, "_update_graph");
1979 	undo_redo->add_undo_method(this, "_update_graph");
1980 	undo_redo->commit_action();
1981 }
1982 
_mode_selected(int p_id)1983 void VisualShaderEditor::_mode_selected(int p_id) {
1984 
1985 	_update_options_menu();
1986 	_update_graph();
1987 }
1988 
_input_select_item(Ref<VisualShaderNodeInput> input,String name)1989 void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> input, String name) {
1990 
1991 	String prev_name = input->get_input_name();
1992 
1993 	if (name == prev_name)
1994 		return;
1995 
1996 	bool type_changed = input->get_input_type_by_name(name) != input->get_input_type_by_name(prev_name);
1997 
1998 	UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
1999 	undo_redo->create_action(TTR("Visual Shader Input Type Changed"));
2000 
2001 	undo_redo->add_do_method(input.ptr(), "set_input_name", name);
2002 	undo_redo->add_undo_method(input.ptr(), "set_input_name", prev_name);
2003 
2004 	if (type_changed) {
2005 		//restore connections if type changed
2006 		VisualShader::Type type = VisualShader::Type(edit_type->get_selected());
2007 		int id = visual_shader->find_node_id(type, input);
2008 		List<VisualShader::Connection> conns;
2009 		visual_shader->get_node_connections(type, &conns);
2010 		for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
2011 			if (E->get().from_node == id) {
2012 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
2013 			}
2014 		}
2015 	}
2016 
2017 	undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_graph");
2018 	undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_graph");
2019 
2020 	undo_redo->commit_action();
2021 }
2022 
_member_filter_changed(const String & p_text)2023 void VisualShaderEditor::_member_filter_changed(const String &p_text) {
2024 	_update_options_menu();
2025 }
2026 
_member_selected()2027 void VisualShaderEditor::_member_selected() {
2028 	TreeItem *item = members->get_selected();
2029 
2030 	if (item != NULL && item->has_meta("id")) {
2031 		members_dialog->get_ok()->set_disabled(false);
2032 		node_desc->set_text(_get_description(item->get_meta("id")));
2033 	} else {
2034 		members_dialog->get_ok()->set_disabled(true);
2035 		node_desc->set_text("");
2036 	}
2037 }
2038 
_member_unselected()2039 void VisualShaderEditor::_member_unselected() {
2040 }
2041 
_member_create()2042 void VisualShaderEditor::_member_create() {
2043 	TreeItem *item = members->get_selected();
2044 	if (item != NULL && item->has_meta("id")) {
2045 		int idx = members->get_selected()->get_meta("id");
2046 		_add_node(idx, add_options[idx].sub_func);
2047 		members_dialog->hide();
2048 	}
2049 }
2050 
_member_cancel()2051 void VisualShaderEditor::_member_cancel() {
2052 	to_node = -1;
2053 	to_slot = -1;
2054 	from_node = -1;
2055 	from_slot = -1;
2056 }
2057 
_tools_menu_option(int p_idx)2058 void VisualShaderEditor::_tools_menu_option(int p_idx) {
2059 
2060 	TreeItem *category = members->get_root()->get_children();
2061 
2062 	switch (p_idx) {
2063 		case EXPAND_ALL:
2064 
2065 			while (category) {
2066 				category->set_collapsed(false);
2067 				TreeItem *sub_category = category->get_children();
2068 				while (sub_category) {
2069 					sub_category->set_collapsed(false);
2070 					sub_category = sub_category->get_next();
2071 				}
2072 				category = category->get_next();
2073 			}
2074 
2075 			break;
2076 
2077 		case COLLAPSE_ALL:
2078 
2079 			while (category) {
2080 				category->set_collapsed(true);
2081 				TreeItem *sub_category = category->get_children();
2082 				while (sub_category) {
2083 					sub_category->set_collapsed(true);
2084 					sub_category = sub_category->get_next();
2085 				}
2086 				category = category->get_next();
2087 			}
2088 
2089 			break;
2090 		default:
2091 			break;
2092 	}
2093 }
2094 
get_drag_data_fw(const Point2 & p_point,Control * p_from)2095 Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
2096 
2097 	if (p_from == members) {
2098 		TreeItem *it = members->get_item_at_position(p_point);
2099 		if (!it)
2100 			return Variant();
2101 		if (!it->has_meta("id"))
2102 			return Variant();
2103 
2104 		int id = it->get_meta("id");
2105 		AddOption op = add_options[id];
2106 
2107 		Dictionary d;
2108 		d["id"] = id;
2109 		if (op.sub_func == -1) {
2110 			d["sub_func"] = op.sub_func_str;
2111 		} else {
2112 			d["sub_func"] = op.sub_func;
2113 		}
2114 
2115 		Label *label = memnew(Label);
2116 		label->set_text(it->get_text(0));
2117 		set_drag_preview(label);
2118 		return d;
2119 	}
2120 	return Variant();
2121 }
2122 
can_drop_data_fw(const Point2 & p_point,const Variant & p_data,Control * p_from) const2123 bool VisualShaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
2124 
2125 	if (p_from == graph) {
2126 
2127 		Dictionary d = p_data;
2128 
2129 		if (d.has("id")) {
2130 			return true;
2131 		}
2132 		if (d.has("files")) {
2133 			return true;
2134 		}
2135 	}
2136 
2137 	return false;
2138 }
2139 
drop_data_fw(const Point2 & p_point,const Variant & p_data,Control * p_from)2140 void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
2141 
2142 	if (p_from == graph) {
2143 
2144 		Dictionary d = p_data;
2145 
2146 		if (d.has("id")) {
2147 			int idx = d["id"];
2148 			saved_node_pos = p_point;
2149 			saved_node_pos_dirty = true;
2150 			_add_node(idx, add_options[idx].sub_func);
2151 		} else if (d.has("files")) {
2152 			if (d["files"].get_type() == Variant::POOL_STRING_ARRAY) {
2153 
2154 				int j = 0;
2155 				PoolStringArray arr = d["files"];
2156 				for (int i = 0; i < arr.size(); i++) {
2157 
2158 					String type = ResourceLoader::get_resource_type(arr[i]);
2159 					if (type == "GDScript") {
2160 						Ref<Script> script = ResourceLoader::load(arr[i]);
2161 						if (script->get_instance_base_type() == "VisualShaderNodeCustom") {
2162 							saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
2163 							saved_node_pos_dirty = true;
2164 							_add_custom_node(arr[i]);
2165 							j++;
2166 						}
2167 					} else if (ClassDB::get_parent_class(type) == "Texture") {
2168 						saved_node_pos = p_point + Vector2(0, j * 210 * EDSCALE);
2169 						saved_node_pos_dirty = true;
2170 						_add_texture_node(arr[i]);
2171 						j++;
2172 					}
2173 				}
2174 			}
2175 		}
2176 	}
2177 }
2178 
_show_preview_text()2179 void VisualShaderEditor::_show_preview_text() {
2180 	preview_showed = !preview_showed;
2181 	preview_vbox->set_visible(preview_showed);
2182 	if (preview_showed) {
2183 		if (pending_update_preview) {
2184 			_update_preview();
2185 			pending_update_preview = false;
2186 		}
2187 	}
2188 }
2189 
_update_preview()2190 void VisualShaderEditor::_update_preview() {
2191 
2192 	if (!preview_showed) {
2193 		pending_update_preview = true;
2194 		return;
2195 	}
2196 
2197 	String code = visual_shader->get_code();
2198 
2199 	preview_text->set_text(code);
2200 
2201 	ShaderLanguage sl;
2202 
2203 	Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types());
2204 
2205 	for (int i = 0; i < preview_text->get_line_count(); i++) {
2206 		preview_text->set_line_as_marked(i, false);
2207 	}
2208 	if (err != OK) {
2209 		preview_text->set_line_as_marked(sl.get_error_line() - 1, true);
2210 		error_text->set_visible(true);
2211 
2212 		String text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text();
2213 		error_text->set_text(text);
2214 		shader_error = true;
2215 	} else {
2216 		error_text->set_visible(false);
2217 		shader_error = false;
2218 	}
2219 }
2220 
_bind_methods()2221 void VisualShaderEditor::_bind_methods() {
2222 	ClassDB::bind_method("_rebuild", &VisualShaderEditor::_rebuild);
2223 	ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
2224 	ClassDB::bind_method("_update_options_menu", &VisualShaderEditor::_update_options_menu);
2225 	ClassDB::bind_method("_expression_focus_out", &VisualShaderEditor::_expression_focus_out);
2226 	ClassDB::bind_method("_add_node", &VisualShaderEditor::_add_node);
2227 	ClassDB::bind_method("_node_dragged", &VisualShaderEditor::_node_dragged);
2228 	ClassDB::bind_method("_connection_request", &VisualShaderEditor::_connection_request);
2229 	ClassDB::bind_method("_disconnection_request", &VisualShaderEditor::_disconnection_request);
2230 	ClassDB::bind_method("_node_selected", &VisualShaderEditor::_node_selected);
2231 	ClassDB::bind_method("_scroll_changed", &VisualShaderEditor::_scroll_changed);
2232 	ClassDB::bind_method("_delete_request", &VisualShaderEditor::_delete_request);
2233 	ClassDB::bind_method("_on_nodes_delete", &VisualShaderEditor::_on_nodes_delete);
2234 	ClassDB::bind_method("_node_changed", &VisualShaderEditor::_node_changed);
2235 	ClassDB::bind_method("_edit_port_default_input", &VisualShaderEditor::_edit_port_default_input);
2236 	ClassDB::bind_method("_port_edited", &VisualShaderEditor::_port_edited);
2237 	ClassDB::bind_method("_connection_to_empty", &VisualShaderEditor::_connection_to_empty);
2238 	ClassDB::bind_method("_connection_from_empty", &VisualShaderEditor::_connection_from_empty);
2239 	ClassDB::bind_method("_line_edit_focus_out", &VisualShaderEditor::_line_edit_focus_out);
2240 	ClassDB::bind_method("_line_edit_changed", &VisualShaderEditor::_line_edit_changed);
2241 	ClassDB::bind_method("_port_name_focus_out", &VisualShaderEditor::_port_name_focus_out);
2242 	ClassDB::bind_method("_duplicate_nodes", &VisualShaderEditor::_duplicate_nodes);
2243 	ClassDB::bind_method("_copy_nodes", &VisualShaderEditor::_copy_nodes);
2244 	ClassDB::bind_method("_paste_nodes", &VisualShaderEditor::_paste_nodes);
2245 	ClassDB::bind_method("_mode_selected", &VisualShaderEditor::_mode_selected);
2246 	ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
2247 	ClassDB::bind_method("_preview_select_port", &VisualShaderEditor::_preview_select_port);
2248 	ClassDB::bind_method("_graph_gui_input", &VisualShaderEditor::_graph_gui_input);
2249 	ClassDB::bind_method("_add_input_port", &VisualShaderEditor::_add_input_port);
2250 	ClassDB::bind_method("_change_input_port_type", &VisualShaderEditor::_change_input_port_type);
2251 	ClassDB::bind_method("_change_input_port_name", &VisualShaderEditor::_change_input_port_name);
2252 	ClassDB::bind_method("_remove_input_port", &VisualShaderEditor::_remove_input_port);
2253 	ClassDB::bind_method("_add_output_port", &VisualShaderEditor::_add_output_port);
2254 	ClassDB::bind_method("_change_output_port_type", &VisualShaderEditor::_change_output_port_type);
2255 	ClassDB::bind_method("_change_output_port_name", &VisualShaderEditor::_change_output_port_name);
2256 	ClassDB::bind_method("_remove_output_port", &VisualShaderEditor::_remove_output_port);
2257 	ClassDB::bind_method("_node_resized", &VisualShaderEditor::_node_resized);
2258 	ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size);
2259 	ClassDB::bind_method("_clear_buffer", &VisualShaderEditor::_clear_buffer);
2260 	ClassDB::bind_method("_show_preview_text", &VisualShaderEditor::_show_preview_text);
2261 	ClassDB::bind_method("_update_preview", &VisualShaderEditor::_update_preview);
2262 
2263 	ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
2264 	ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
2265 	ClassDB::bind_method(D_METHOD("drop_data_fw"), &VisualShaderEditor::drop_data_fw);
2266 
2267 	ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available);
2268 	ClassDB::bind_method("_tools_menu_option", &VisualShaderEditor::_tools_menu_option);
2269 	ClassDB::bind_method("_show_members_dialog", &VisualShaderEditor::_show_members_dialog);
2270 	ClassDB::bind_method("_sbox_input", &VisualShaderEditor::_sbox_input);
2271 	ClassDB::bind_method("_member_filter_changed", &VisualShaderEditor::_member_filter_changed);
2272 	ClassDB::bind_method("_member_selected", &VisualShaderEditor::_member_selected);
2273 	ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected);
2274 	ClassDB::bind_method("_member_create", &VisualShaderEditor::_member_create);
2275 	ClassDB::bind_method("_member_cancel", &VisualShaderEditor::_member_cancel);
2276 }
2277 
2278 VisualShaderEditor *VisualShaderEditor::singleton = NULL;
2279 
VisualShaderEditor()2280 VisualShaderEditor::VisualShaderEditor() {
2281 
2282 	singleton = this;
2283 	updating = false;
2284 	saved_node_pos_dirty = false;
2285 	saved_node_pos = Point2(0, 0);
2286 	ShaderLanguage::get_keyword_list(&keyword_list);
2287 
2288 	preview_showed = false;
2289 	pending_update_preview = false;
2290 	shader_error = false;
2291 
2292 	to_node = -1;
2293 	to_slot = -1;
2294 	from_node = -1;
2295 	from_slot = -1;
2296 
2297 	main_box = memnew(HSplitContainer);
2298 	main_box->set_v_size_flags(SIZE_EXPAND_FILL);
2299 	main_box->set_h_size_flags(SIZE_EXPAND_FILL);
2300 	add_child(main_box);
2301 
2302 	graph = memnew(GraphEdit);
2303 	graph->get_zoom_hbox()->set_h_size_flags(SIZE_EXPAND_FILL);
2304 	graph->set_v_size_flags(SIZE_EXPAND_FILL);
2305 	graph->set_h_size_flags(SIZE_EXPAND_FILL);
2306 	main_box->add_child(graph);
2307 	graph->set_drag_forwarding(this);
2308 	graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR);
2309 	graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN);
2310 	graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR);
2311 	graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM);
2312 	graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
2313 	//graph->add_valid_left_disconnect_type(0);
2314 	graph->set_v_size_flags(SIZE_EXPAND_FILL);
2315 	graph->connect("connection_request", this, "_connection_request", varray(), CONNECT_DEFERRED);
2316 	graph->connect("disconnection_request", this, "_disconnection_request", varray(), CONNECT_DEFERRED);
2317 	graph->connect("node_selected", this, "_node_selected");
2318 	graph->connect("scroll_offset_changed", this, "_scroll_changed");
2319 	graph->connect("duplicate_nodes_request", this, "_duplicate_nodes");
2320 	graph->connect("copy_nodes_request", this, "_copy_nodes");
2321 	graph->connect("paste_nodes_request", this, "_paste_nodes");
2322 	graph->connect("delete_nodes_request", this, "_on_nodes_delete");
2323 	graph->connect("gui_input", this, "_graph_gui_input");
2324 	graph->connect("connection_to_empty", this, "_connection_to_empty");
2325 	graph->connect("connection_from_empty", this, "_connection_from_empty");
2326 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
2327 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR);
2328 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
2329 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_SCALAR);
2330 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_VECTOR);
2331 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR, VisualShaderNode::PORT_TYPE_BOOLEAN);
2332 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR);
2333 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR);
2334 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN);
2335 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
2336 	graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
2337 
2338 	VSeparator *vs = memnew(VSeparator);
2339 	graph->get_zoom_hbox()->add_child(vs);
2340 	graph->get_zoom_hbox()->move_child(vs, 0);
2341 
2342 	edit_type = memnew(OptionButton);
2343 	edit_type->add_item(TTR("Vertex"));
2344 	edit_type->add_item(TTR("Fragment"));
2345 	edit_type->add_item(TTR("Light"));
2346 	edit_type->select(1);
2347 	edit_type->connect("item_selected", this, "_mode_selected");
2348 	graph->get_zoom_hbox()->add_child(edit_type);
2349 	graph->get_zoom_hbox()->move_child(edit_type, 0);
2350 
2351 	add_node = memnew(ToolButton);
2352 	graph->get_zoom_hbox()->add_child(add_node);
2353 	add_node->set_text(TTR("Add Node..."));
2354 	graph->get_zoom_hbox()->move_child(add_node, 0);
2355 	add_node->connect("pressed", this, "_show_members_dialog", varray(false));
2356 
2357 	preview_shader = memnew(ToolButton);
2358 	preview_shader->set_toggle_mode(true);
2359 	preview_shader->set_tooltip(TTR("Show resulted shader code."));
2360 	graph->get_zoom_hbox()->add_child(preview_shader);
2361 	preview_shader->connect("pressed", this, "_show_preview_text");
2362 
2363 	///////////////////////////////////////
2364 	// PREVIEW PANEL
2365 	///////////////////////////////////////
2366 
2367 	preview_vbox = memnew(VBoxContainer);
2368 	preview_vbox->set_visible(preview_showed);
2369 	main_box->add_child(preview_vbox);
2370 	preview_text = memnew(TextEdit);
2371 	preview_vbox->add_child(preview_text);
2372 	preview_text->set_h_size_flags(SIZE_EXPAND_FILL);
2373 	preview_text->set_v_size_flags(SIZE_EXPAND_FILL);
2374 	preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
2375 	preview_text->set_syntax_coloring(true);
2376 	preview_text->set_show_line_numbers(true);
2377 	preview_text->set_readonly(true);
2378 
2379 	error_text = memnew(Label);
2380 	preview_vbox->add_child(error_text);
2381 	error_text->set_visible(false);
2382 
2383 	///////////////////////////////////////
2384 	// SHADER NODES TREE
2385 	///////////////////////////////////////
2386 
2387 	VBoxContainer *members_vb = memnew(VBoxContainer);
2388 	members_vb->set_v_size_flags(SIZE_EXPAND_FILL);
2389 
2390 	HBoxContainer *filter_hb = memnew(HBoxContainer);
2391 	members_vb->add_child(filter_hb);
2392 
2393 	node_filter = memnew(LineEdit);
2394 	filter_hb->add_child(node_filter);
2395 	node_filter->connect("text_changed", this, "_member_filter_changed");
2396 	node_filter->connect("gui_input", this, "_sbox_input");
2397 	node_filter->set_h_size_flags(SIZE_EXPAND_FILL);
2398 	node_filter->set_placeholder(TTR("Search"));
2399 
2400 	tools = memnew(MenuButton);
2401 	filter_hb->add_child(tools);
2402 	tools->set_tooltip(TTR("Options"));
2403 	tools->get_popup()->connect("id_pressed", this, "_tools_menu_option");
2404 	tools->get_popup()->add_item(TTR("Expand All"), EXPAND_ALL);
2405 	tools->get_popup()->add_item(TTR("Collapse All"), COLLAPSE_ALL);
2406 
2407 	members = memnew(Tree);
2408 	members_vb->add_child(members);
2409 	members->set_drag_forwarding(this);
2410 	members->set_h_size_flags(SIZE_EXPAND_FILL);
2411 	members->set_v_size_flags(SIZE_EXPAND_FILL);
2412 	members->set_hide_root(true);
2413 	members->set_allow_reselect(true);
2414 	members->set_hide_folding(false);
2415 	members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
2416 	members->connect("item_activated", this, "_member_create");
2417 	members->connect("item_selected", this, "_member_selected");
2418 	members->connect("nothing_selected", this, "_member_unselected");
2419 
2420 	Label *desc_label = memnew(Label);
2421 	members_vb->add_child(desc_label);
2422 	desc_label->set_text(TTR("Description:"));
2423 
2424 	node_desc = memnew(RichTextLabel);
2425 	members_vb->add_child(node_desc);
2426 	node_desc->set_h_size_flags(SIZE_EXPAND_FILL);
2427 	node_desc->set_v_size_flags(SIZE_FILL);
2428 	node_desc->set_custom_minimum_size(Size2(0, 70 * EDSCALE));
2429 
2430 	members_dialog = memnew(ConfirmationDialog);
2431 	members_dialog->set_title(TTR("Create Shader Node"));
2432 	members_dialog->add_child(members_vb);
2433 	members_dialog->get_ok()->set_text(TTR("Create"));
2434 	members_dialog->get_ok()->connect("pressed", this, "_member_create");
2435 	members_dialog->get_ok()->set_disabled(true);
2436 	members_dialog->set_resizable(true);
2437 	members_dialog->set_as_minsize();
2438 	members_dialog->connect("hide", this, "_member_cancel");
2439 	add_child(members_dialog);
2440 
2441 	alert = memnew(AcceptDialog);
2442 	alert->set_as_minsize();
2443 	alert->get_label()->set_autowrap(true);
2444 	alert->get_label()->set_align(Label::ALIGN_CENTER);
2445 	alert->get_label()->set_valign(Label::VALIGN_CENTER);
2446 	alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE);
2447 	add_child(alert);
2448 
2449 	///////////////////////////////////////
2450 	// SHADER NODES TREE OPTIONS
2451 	///////////////////////////////////////
2452 
2453 	// COLOR
2454 
2455 	add_options.push_back(AddOption("ColorFunc", "Color", "Common", "VisualShaderNodeColorFunc", TTR("Color function."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2456 	add_options.push_back(AddOption("ColorOp", "Color", "Common", "VisualShaderNodeColorOp", TTR("Color operator."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2457 
2458 	add_options.push_back(AddOption("Grayscale", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), VisualShaderNodeColorFunc::FUNC_GRAYSCALE, VisualShaderNode::PORT_TYPE_VECTOR));
2459 	add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts HSV vector to RGB equivalent."), VisualShaderNodeVectorFunc::FUNC_HSV2RGB, VisualShaderNode::PORT_TYPE_VECTOR));
2460 	add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts RGB vector to HSV equivalent."), VisualShaderNodeVectorFunc::FUNC_RGB2HSV, VisualShaderNode::PORT_TYPE_VECTOR));
2461 	add_options.push_back(AddOption("Sepia", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), VisualShaderNodeColorFunc::FUNC_SEPIA, VisualShaderNode::PORT_TYPE_VECTOR));
2462 
2463 	add_options.push_back(AddOption("Burn", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), VisualShaderNodeColorOp::OP_BURN, VisualShaderNode::PORT_TYPE_VECTOR));
2464 	add_options.push_back(AddOption("Darken", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), VisualShaderNodeColorOp::OP_DARKEN, VisualShaderNode::PORT_TYPE_VECTOR));
2465 	add_options.push_back(AddOption("Difference", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Difference operator."), VisualShaderNodeColorOp::OP_DIFFERENCE, VisualShaderNode::PORT_TYPE_VECTOR));
2466 	add_options.push_back(AddOption("Dodge", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Dodge operator."), VisualShaderNodeColorOp::OP_DODGE, VisualShaderNode::PORT_TYPE_VECTOR));
2467 	add_options.push_back(AddOption("HardLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("HardLight operator."), VisualShaderNodeColorOp::OP_HARD_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR));
2468 	add_options.push_back(AddOption("Lighten", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Lighten operator."), VisualShaderNodeColorOp::OP_LIGHTEN, VisualShaderNode::PORT_TYPE_VECTOR));
2469 	add_options.push_back(AddOption("Overlay", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Overlay operator."), VisualShaderNodeColorOp::OP_OVERLAY, VisualShaderNode::PORT_TYPE_VECTOR));
2470 	add_options.push_back(AddOption("Screen", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), VisualShaderNodeColorOp::OP_SCREEN, VisualShaderNode::PORT_TYPE_VECTOR));
2471 	add_options.push_back(AddOption("SoftLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), VisualShaderNodeColorOp::OP_SOFT_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR));
2472 
2473 	add_options.push_back(AddOption("ColorConstant", "Color", "Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), -1, -1));
2474 	add_options.push_back(AddOption("ColorUniform", "Color", "Variables", "VisualShaderNodeColorUniform", TTR("Color uniform."), -1, -1));
2475 
2476 	// CONDITIONAL
2477 
2478 	const String &compare_func_desc = TTR("Returns the boolean result of the %s comparison between two parameters.");
2479 
2480 	add_options.push_back(AddOption("Equal", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Equal (==)")), VisualShaderNodeCompare::FUNC_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN));
2481 	add_options.push_back(AddOption("GreaterThan", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Greater Than (>)")), VisualShaderNodeCompare::FUNC_GREATER_THAN, VisualShaderNode::PORT_TYPE_BOOLEAN));
2482 	add_options.push_back(AddOption("GreaterThanEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Greater Than or Equal (>=)")), VisualShaderNodeCompare::FUNC_GREATER_THAN_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN));
2483 	add_options.push_back(AddOption("If", "Conditional", "Functions", "VisualShaderNodeIf", TTR("Returns an associated vector if the provided scalars are equal, greater or less."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2484 	add_options.push_back(AddOption("IsInf", "Conditional", "Functions", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between INF and a scalar parameter."), VisualShaderNodeIs::FUNC_IS_INF, VisualShaderNode::PORT_TYPE_BOOLEAN));
2485 	add_options.push_back(AddOption("IsNaN", "Conditional", "Functions", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between NaN and a scalar parameter."), VisualShaderNodeIs::FUNC_IS_NAN, VisualShaderNode::PORT_TYPE_BOOLEAN));
2486 	add_options.push_back(AddOption("LessThan", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than (<)")), VisualShaderNodeCompare::FUNC_LESS_THAN, VisualShaderNode::PORT_TYPE_BOOLEAN));
2487 	add_options.push_back(AddOption("LessThanEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than or Equal (<=)")), VisualShaderNodeCompare::FUNC_LESS_THAN_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN));
2488 	add_options.push_back(AddOption("NotEqual", "Conditional", "Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Not Equal (!=)")), VisualShaderNodeCompare::FUNC_NOT_EQUAL, VisualShaderNode::PORT_TYPE_BOOLEAN));
2489 	add_options.push_back(AddOption("Switch", "Conditional", "Functions", "VisualShaderNodeSwitch", TTR("Returns an associated vector if the provided boolean value is true or false."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2490 	add_options.push_back(AddOption("SwitchS", "Conditional", "Functions", "VisualShaderNodeScalarSwitch", TTR("Returns an associated scalar if the provided boolean value is true or false."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2491 
2492 	add_options.push_back(AddOption("Compare", "Conditional", "Common", "VisualShaderNodeCompare", TTR("Returns the boolean result of the comparison between two parameters."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN));
2493 	add_options.push_back(AddOption("Is", "Conditional", "Common", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between INF (or NaN) and a scalar parameter."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN));
2494 
2495 	add_options.push_back(AddOption("BooleanConstant", "Conditional", "Variables", "VisualShaderNodeBooleanConstant", TTR("Boolean constant."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN));
2496 	add_options.push_back(AddOption("BooleanUniform", "Conditional", "Variables", "VisualShaderNodeBooleanUniform", TTR("Boolean uniform."), -1, VisualShaderNode::PORT_TYPE_BOOLEAN));
2497 
2498 	// INPUT
2499 
2500 	// SPATIAL-FOR-ALL
2501 	const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes.");
2502 	add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
2503 	add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_camera"), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
2504 	add_options.push_back(AddOption("InvProjection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_projection"), "inv_projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
2505 	add_options.push_back(AddOption("Normal", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "normal"), "normal", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL));
2506 	add_options.push_back(AddOption("OutputIsSRGB", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "output_is_srgb"), "output_is_srgb", VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_SPATIAL));
2507 	add_options.push_back(AddOption("Projection", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
2508 	add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
2509 	add_options.push_back(AddOption("ViewportSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "viewport_size"), "viewport_size", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_SPATIAL));
2510 	add_options.push_back(AddOption("World", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "world"), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
2511 
2512 	// CANVASITEM-FOR-ALL
2513 
2514 	add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
2515 	add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM));
2516 	add_options.push_back(AddOption("ModulateAlpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "modulate_alpha"), "modulate_alpha", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
2517 	add_options.push_back(AddOption("ModulateColor", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "modulate_color"), "modulate_color", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM));
2518 	add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size"), "texture_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM));
2519 	add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
2520 	add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, -1, Shader::MODE_CANVAS_ITEM));
2521 
2522 	/////////////////
2523 
2524 	add_options.push_back(AddOption("Input", "Input", "Common", "VisualShaderNodeInput", TTR("Input parameter.")));
2525 
2526 	// SPATIAL INPUTS
2527 
2528 	const String input_param_for_vertex_and_fragment_shader_modes = TTR("'%s' input parameter for vertex and fragment shader modes.");
2529 	const String input_param_for_fragment_and_light_shader_modes = TTR("'%s' input parameter for fragment and light shader modes.");
2530 	const String input_param_for_fragment_shader_mode = TTR("'%s' input parameter for fragment shader mode.");
2531 	const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode.");
2532 	const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode.");
2533 	const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader mode.");
2534 
2535 	add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2536 	add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2537 	add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2538 	add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture"), "depth_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2539 	add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2540 	add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), "front_facing", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2541 	add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2542 	add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2543 	add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2544 	add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "side"), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2545 	add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2546 	add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2547 	add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2548 	add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2549 	add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL));
2550 
2551 	add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo"), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2552 	add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation"), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2553 	add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse"), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2554 	add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2555 	add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light"), "light", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2556 	add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2557 	add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness"), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2558 	add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular"), "specular", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2559 	add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "transmission"), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2560 	add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2561 
2562 	add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2563 	add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2564 	add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2565 	add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview"), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2566 	add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2567 	add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2568 	add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2569 	add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2570 	add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL));
2571 
2572 	// CANVASITEM INPUTS
2573 
2574 	add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2575 	add_options.push_back(AddOption("LightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2576 	add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture"), "normal_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2577 	add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2578 	add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), "screen_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2579 	add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2580 	add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2581 	add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM));
2582 
2583 	add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2584 	add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha"), "light_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2585 	add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2586 	add_options.push_back(AddOption("LightHeight", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_height"), "light_height", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2587 	add_options.push_back(AddOption("LightUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_uv"), "light_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2588 	add_options.push_back(AddOption("LightVector", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_vec"), "light_vec", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2589 	add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal"), "normal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2590 	add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2591 	add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2592 	add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha"), "shadow_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2593 	add_options.push_back(AddOption("ShadowColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_color"), "shadow_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2594 	add_options.push_back(AddOption("ShadowVec", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_vec"), "shadow_vec", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2595 	add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM));
2596 
2597 	add_options.push_back(AddOption("Extra", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "extra"), "extra", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2598 	add_options.push_back(AddOption("LightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2599 	add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2600 	add_options.push_back(AddOption("Projection", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "projection"), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2601 	add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2602 	add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM));
2603 
2604 	// PARTICLES INPUTS
2605 
2606 	add_options.push_back(AddOption("Active", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2607 	add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2608 	add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2609 	add_options.push_back(AddOption("Custom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2610 	add_options.push_back(AddOption("CustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2611 	add_options.push_back(AddOption("Delta", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2612 	add_options.push_back(AddOption("EmissionTransform", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2613 	add_options.push_back(AddOption("Index", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2614 	add_options.push_back(AddOption("LifeTime", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2615 	add_options.push_back(AddOption("Restart", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2616 	add_options.push_back(AddOption("Time", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2617 	add_options.push_back(AddOption("Transform", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2618 	add_options.push_back(AddOption("Velocity", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES));
2619 
2620 	// SCALAR
2621 
2622 	add_options.push_back(AddOption("ScalarFunc", "Scalar", "Common", "VisualShaderNodeScalarFunc", TTR("Scalar function."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2623 	add_options.push_back(AddOption("ScalarOp", "Scalar", "Common", "VisualShaderNodeScalarOp", TTR("Scalar operator."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2624 
2625 	//CONSTANTS
2626 
2627 	add_options.push_back(AddOption("E", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("E constant (2.718282). Represents the base of the natural logarithm."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_E));
2628 	add_options.push_back(AddOption("Epsilon", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Epsilon constant (0.00001). Smallest possible scalar number."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, CMP_EPSILON));
2629 	add_options.push_back(AddOption("Phi", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Phi constant (1.618034). Golden ratio."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, 1.618034f));
2630 	add_options.push_back(AddOption("Pi/4", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi/4 constant (0.785398) or 45 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI / 4));
2631 	add_options.push_back(AddOption("Pi/2", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi/2 constant (1.570796) or 90 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI / 2));
2632 	add_options.push_back(AddOption("Pi", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Pi constant (3.141593) or 180 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_PI));
2633 	add_options.push_back(AddOption("Tau", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Tau constant (6.283185) or 360 degrees."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_TAU));
2634 	add_options.push_back(AddOption("Sqrt2", "Scalar", "Constants", "VisualShaderNodeScalarConstant", TTR("Sqrt2 constant (1.414214). Square root of 2."), -1, VisualShaderNode::PORT_TYPE_SCALAR, -1, -1, Math_SQRT2));
2635 
2636 	// FUNCTIONS
2637 
2638 	add_options.push_back(AddOption("Abs", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the absolute value of the parameter."), VisualShaderNodeScalarFunc::FUNC_ABS, VisualShaderNode::PORT_TYPE_SCALAR));
2639 	add_options.push_back(AddOption("ACos", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOS, VisualShaderNode::PORT_TYPE_SCALAR));
2640 	add_options.push_back(AddOption("ACosH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ACOSH, VisualShaderNode::PORT_TYPE_SCALAR));
2641 	add_options.push_back(AddOption("ASin", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ASIN, VisualShaderNode::PORT_TYPE_SCALAR));
2642 	add_options.push_back(AddOption("ASinH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_ASINH, VisualShaderNode::PORT_TYPE_SCALAR));
2643 	add_options.push_back(AddOption("ATan", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the arc-tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_ATAN, VisualShaderNode::PORT_TYPE_SCALAR));
2644 	add_options.push_back(AddOption("ATan2", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the arc-tangent of the parameters."), VisualShaderNodeScalarOp::OP_ATAN2, VisualShaderNode::PORT_TYPE_SCALAR));
2645 	add_options.push_back(AddOption("ATanH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_ATANH, VisualShaderNode::PORT_TYPE_SCALAR));
2646 	add_options.push_back(AddOption("Ceil", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), VisualShaderNodeScalarFunc::FUNC_CEIL, VisualShaderNode::PORT_TYPE_SCALAR));
2647 	add_options.push_back(AddOption("Clamp", "Scalar", "Functions", "VisualShaderNodeScalarClamp", TTR("Constrains a value to lie between two further values."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2648 	add_options.push_back(AddOption("Cos", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_COS, VisualShaderNode::PORT_TYPE_SCALAR));
2649 	add_options.push_back(AddOption("CosH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the hyperbolic cosine of the parameter."), VisualShaderNodeScalarFunc::FUNC_COSH, VisualShaderNode::PORT_TYPE_SCALAR));
2650 	add_options.push_back(AddOption("Degrees", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Converts a quantity in radians to degrees."), VisualShaderNodeScalarFunc::FUNC_DEGREES, VisualShaderNode::PORT_TYPE_SCALAR));
2651 	add_options.push_back(AddOption("Exp", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-e Exponential."), VisualShaderNodeScalarFunc::FUNC_EXP, VisualShaderNode::PORT_TYPE_SCALAR));
2652 	add_options.push_back(AddOption("Exp2", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-2 Exponential."), VisualShaderNodeScalarFunc::FUNC_EXP2, VisualShaderNode::PORT_TYPE_SCALAR));
2653 	add_options.push_back(AddOption("Floor", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest integer less than or equal to the parameter."), VisualShaderNodeScalarFunc::FUNC_FLOOR, VisualShaderNode::PORT_TYPE_SCALAR));
2654 	add_options.push_back(AddOption("Fract", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Computes the fractional part of the argument."), VisualShaderNodeScalarFunc::FUNC_FRAC, VisualShaderNode::PORT_TYPE_SCALAR));
2655 	add_options.push_back(AddOption("InverseSqrt", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the inverse of the square root of the parameter."), VisualShaderNodeScalarFunc::FUNC_INVERSE_SQRT, VisualShaderNode::PORT_TYPE_SCALAR));
2656 	add_options.push_back(AddOption("Log", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Natural logarithm."), VisualShaderNodeScalarFunc::FUNC_LOG, VisualShaderNode::PORT_TYPE_SCALAR));
2657 	add_options.push_back(AddOption("Log2", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Base-2 logarithm."), VisualShaderNodeScalarFunc::FUNC_LOG2, VisualShaderNode::PORT_TYPE_SCALAR));
2658 	add_options.push_back(AddOption("Max", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the greater of two values."), VisualShaderNodeScalarOp::OP_MAX, VisualShaderNode::PORT_TYPE_SCALAR));
2659 	add_options.push_back(AddOption("Min", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the lesser of two values."), VisualShaderNodeScalarOp::OP_MIN, VisualShaderNode::PORT_TYPE_SCALAR));
2660 	add_options.push_back(AddOption("Mix", "Scalar", "Functions", "VisualShaderNodeScalarInterp", TTR("Linear interpolation between two scalars."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2661 	add_options.push_back(AddOption("Negate", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeScalarFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_SCALAR));
2662 	add_options.push_back(AddOption("OneMinus", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("1.0 - scalar"), VisualShaderNodeScalarFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_SCALAR));
2663 	add_options.push_back(AddOption("Pow", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Returns the value of the first parameter raised to the power of the second."), VisualShaderNodeScalarOp::OP_POW, VisualShaderNode::PORT_TYPE_SCALAR));
2664 	add_options.push_back(AddOption("Radians", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Converts a quantity in degrees to radians."), VisualShaderNodeScalarFunc::FUNC_RADIANS, VisualShaderNode::PORT_TYPE_SCALAR));
2665 	add_options.push_back(AddOption("Reciprocal", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("1.0 / scalar"), VisualShaderNodeScalarFunc::FUNC_RECIPROCAL, VisualShaderNode::PORT_TYPE_SCALAR));
2666 	add_options.push_back(AddOption("Round", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest integer to the parameter."), VisualShaderNodeScalarFunc::FUNC_ROUND, VisualShaderNode::PORT_TYPE_SCALAR));
2667 	add_options.push_back(AddOption("RoundEven", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the nearest even integer to the parameter."), VisualShaderNodeScalarFunc::FUNC_ROUNDEVEN, VisualShaderNode::PORT_TYPE_SCALAR));
2668 	add_options.push_back(AddOption("Saturate", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Clamps the value between 0.0 and 1.0."), VisualShaderNodeScalarFunc::FUNC_SATURATE, VisualShaderNode::PORT_TYPE_SCALAR));
2669 	add_options.push_back(AddOption("Sign", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Extracts the sign of the parameter."), VisualShaderNodeScalarFunc::FUNC_SIGN, VisualShaderNode::PORT_TYPE_SCALAR));
2670 	add_options.push_back(AddOption("Sin", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_SIN, VisualShaderNode::PORT_TYPE_SCALAR));
2671 	add_options.push_back(AddOption("SinH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the hyperbolic sine of the parameter."), VisualShaderNodeScalarFunc::FUNC_SINH, VisualShaderNode::PORT_TYPE_SCALAR));
2672 	add_options.push_back(AddOption("Sqrt", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the square root of the parameter."), VisualShaderNodeScalarFunc::FUNC_SQRT, VisualShaderNode::PORT_TYPE_SCALAR));
2673 	add_options.push_back(AddOption("SmoothStep", "Scalar", "Functions", "VisualShaderNodeScalarSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if x is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2674 	add_options.push_back(AddOption("Step", "Scalar", "Functions", "VisualShaderNodeScalarOp", TTR("Step function( scalar(edge), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), VisualShaderNodeScalarOp::OP_STEP, VisualShaderNode::PORT_TYPE_SCALAR));
2675 	add_options.push_back(AddOption("Tan", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_TAN, VisualShaderNode::PORT_TYPE_SCALAR));
2676 	add_options.push_back(AddOption("TanH", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Returns the hyperbolic tangent of the parameter."), VisualShaderNodeScalarFunc::FUNC_TANH, VisualShaderNode::PORT_TYPE_SCALAR));
2677 	add_options.push_back(AddOption("Trunc", "Scalar", "Functions", "VisualShaderNodeScalarFunc", TTR("Finds the truncated value of the parameter."), VisualShaderNodeScalarFunc::FUNC_TRUNC, VisualShaderNode::PORT_TYPE_SCALAR));
2678 
2679 	add_options.push_back(AddOption("Add", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Adds scalar to scalar."), VisualShaderNodeScalarOp::OP_ADD, VisualShaderNode::PORT_TYPE_SCALAR));
2680 	add_options.push_back(AddOption("Divide", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Divides scalar by scalar."), VisualShaderNodeScalarOp::OP_DIV, VisualShaderNode::PORT_TYPE_SCALAR));
2681 	add_options.push_back(AddOption("Multiply", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Multiplies scalar by scalar."), VisualShaderNodeScalarOp::OP_MUL, VisualShaderNode::PORT_TYPE_SCALAR));
2682 	add_options.push_back(AddOption("Remainder", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Returns the remainder of the two scalars."), VisualShaderNodeScalarOp::OP_MOD, VisualShaderNode::PORT_TYPE_SCALAR));
2683 	add_options.push_back(AddOption("Subtract", "Scalar", "Operators", "VisualShaderNodeScalarOp", TTR("Subtracts scalar from scalar."), VisualShaderNodeScalarOp::OP_SUB, VisualShaderNode::PORT_TYPE_SCALAR));
2684 
2685 	add_options.push_back(AddOption("ScalarConstant", "Scalar", "Variables", "VisualShaderNodeScalarConstant", TTR("Scalar constant."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2686 	add_options.push_back(AddOption("ScalarUniform", "Scalar", "Variables", "VisualShaderNodeScalarUniform", TTR("Scalar uniform."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2687 
2688 	// TEXTURES
2689 
2690 	add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubeMap", TTR("Perform the cubic texture lookup."), -1, -1));
2691 	texture_node_option_idx = add_options.size();
2692 	add_options.push_back(AddOption("Texture", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, -1));
2693 
2694 	add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubeMapUniform", TTR("Cubic texture uniform lookup."), -1, -1));
2695 	add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1));
2696 	add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, -1, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL));
2697 
2698 	// TRANSFORM
2699 
2700 	add_options.push_back(AddOption("TransformFunc", "Transform", "Common", "VisualShaderNodeTransformFunc", TTR("Transform function."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2701 
2702 	add_options.push_back(AddOption("OuterProduct", "Transform", "Composition", "VisualShaderNodeOuterProduct", TTR("Calculate the outer product of a pair of vectors.\n\nOuterProduct treats the first parameter 'c' as a column vector (matrix with one column) and the second parameter 'r' as a row vector (matrix with one row) and does a linear algebraic matrix multiply 'c * r', yielding a matrix whose number of rows is the number of components in 'c' and whose number of columns is the number of components in 'r'."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2703 	add_options.push_back(AddOption("TransformCompose", "Transform", "Composition", "VisualShaderNodeTransformCompose", TTR("Composes transform from four vectors."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2704 	add_options.push_back(AddOption("TransformDecompose", "Transform", "Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors.")));
2705 
2706 	add_options.push_back(AddOption("Determinant", "Transform", "Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2707 	add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
2708 	add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM));
2709 
2710 	add_options.push_back(AddOption("TransformMult", "Transform", "Operators", "VisualShaderNodeTransformMult", TTR("Multiplies transform by transform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2711 	add_options.push_back(AddOption("TransformVectorMult", "Transform", "Operators", "VisualShaderNodeTransformVecMult", TTR("Multiplies vector by transform."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2712 
2713 	add_options.push_back(AddOption("TransformConstant", "Transform", "Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2714 	add_options.push_back(AddOption("TransformUniform", "Transform", "Variables", "VisualShaderNodeTransformUniform", TTR("Transform uniform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM));
2715 
2716 	// VECTOR
2717 
2718 	add_options.push_back(AddOption("VectorFunc", "Vector", "Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2719 	add_options.push_back(AddOption("VectorOp", "Vector", "Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2720 
2721 	add_options.push_back(AddOption("VectorCompose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes vector from three scalars."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2722 	add_options.push_back(AddOption("VectorDecompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to three scalars.")));
2723 
2724 	add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNode::PORT_TYPE_VECTOR));
2725 	add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNode::PORT_TYPE_VECTOR));
2726 	add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNode::PORT_TYPE_VECTOR));
2727 	add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNode::PORT_TYPE_VECTOR));
2728 	add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNode::PORT_TYPE_VECTOR));
2729 	add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNode::PORT_TYPE_VECTOR));
2730 	add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNode::PORT_TYPE_VECTOR));
2731 	add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNode::PORT_TYPE_VECTOR));
2732 	add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNode::PORT_TYPE_VECTOR));
2733 	add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeVectorClamp", TTR("Constrains a value to lie between two further values."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2734 	add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNode::PORT_TYPE_VECTOR));
2735 	add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNode::PORT_TYPE_VECTOR));
2736 	add_options.push_back(AddOption("Cross", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), VisualShaderNodeVectorOp::OP_CROSS, VisualShaderNode::PORT_TYPE_VECTOR));
2737 	add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNode::PORT_TYPE_VECTOR));
2738 	add_options.push_back(AddOption("Distance", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2739 	add_options.push_back(AddOption("Dot", "Vector", "Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2740 	add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNode::PORT_TYPE_VECTOR));
2741 	add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNode::PORT_TYPE_VECTOR));
2742 	add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2743 	add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNode::PORT_TYPE_VECTOR));
2744 	add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNode::PORT_TYPE_VECTOR));
2745 	add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNode::PORT_TYPE_VECTOR));
2746 	add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2747 	add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNode::PORT_TYPE_VECTOR));
2748 	add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNode::PORT_TYPE_VECTOR));
2749 	add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), VisualShaderNodeVectorOp::OP_MAX, VisualShaderNode::PORT_TYPE_VECTOR));
2750 	add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), VisualShaderNodeVectorOp::OP_MIN, VisualShaderNode::PORT_TYPE_VECTOR));
2751 	add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeVectorInterp", TTR("Linear interpolation between two vectors."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2752 	add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeVectorScalarMix", TTR("Linear interpolation between two vectors using scalar."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2753 	add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNode::PORT_TYPE_VECTOR));
2754 	add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNode::PORT_TYPE_VECTOR));
2755 	add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNode::PORT_TYPE_VECTOR));
2756 	add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), VisualShaderNodeVectorOp::OP_POW, VisualShaderNode::PORT_TYPE_VECTOR));
2757 	add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNode::PORT_TYPE_VECTOR));
2758 	add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNode::PORT_TYPE_VECTOR));
2759 	add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNode::PORT_TYPE_VECTOR));
2760 	add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2761 	add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNode::PORT_TYPE_VECTOR));
2762 	add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNode::PORT_TYPE_VECTOR));
2763 	add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNode::PORT_TYPE_VECTOR));
2764 	add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNode::PORT_TYPE_VECTOR));
2765 	add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNode::PORT_TYPE_VECTOR));
2766 	add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNode::PORT_TYPE_VECTOR));
2767 	add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNode::PORT_TYPE_VECTOR));
2768 	add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeVectorSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2769 	add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeVectorScalarSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2770 	add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), VisualShaderNodeVectorOp::OP_STEP, VisualShaderNode::PORT_TYPE_VECTOR));
2771 	add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeVectorScalarStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2772 	add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNode::PORT_TYPE_VECTOR));
2773 	add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNode::PORT_TYPE_VECTOR));
2774 	add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNode::PORT_TYPE_VECTOR));
2775 
2776 	add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds vector to vector."), VisualShaderNodeVectorOp::OP_ADD, VisualShaderNode::PORT_TYPE_VECTOR));
2777 	add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides vector by vector."), VisualShaderNodeVectorOp::OP_DIV, VisualShaderNode::PORT_TYPE_VECTOR));
2778 	add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies vector by vector."), VisualShaderNodeVectorOp::OP_MUL, VisualShaderNode::PORT_TYPE_VECTOR));
2779 	add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two vectors."), VisualShaderNodeVectorOp::OP_MOD, VisualShaderNode::PORT_TYPE_VECTOR));
2780 	add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts vector from vector."), VisualShaderNodeVectorOp::OP_SUB, VisualShaderNode::PORT_TYPE_VECTOR));
2781 
2782 	add_options.push_back(AddOption("VectorConstant", "Vector", "Variables", "VisualShaderNodeVec3Constant", TTR("Vector constant."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2783 	add_options.push_back(AddOption("VectorUniform", "Vector", "Variables", "VisualShaderNodeVec3Uniform", TTR("Vector uniform."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
2784 
2785 	// SPECIAL
2786 
2787 	add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside.")));
2788 	add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR));
2789 	add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants.")));
2790 
2791 	add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2792 	add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2793 
2794 	add_options.push_back(AddOption("DdX", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2795 	add_options.push_back(AddOption("DdXS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'x' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2796 	add_options.push_back(AddOption("DdY", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2797 	add_options.push_back(AddOption("DdYS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2798 	add_options.push_back(AddOption("Sum", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeVectorDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2799 	add_options.push_back(AddOption("SumS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeScalarDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true));
2800 	custom_node_option_idx = add_options.size();
2801 
2802 	/////////////////////////////////////////////////////////////////////
2803 
2804 	_update_options_menu();
2805 
2806 	error_panel = memnew(PanelContainer);
2807 	add_child(error_panel);
2808 	error_label = memnew(Label);
2809 	error_panel->add_child(error_label);
2810 	error_label->set_text("eh");
2811 	error_panel->hide();
2812 
2813 	undo_redo = EditorNode::get_singleton()->get_undo_redo();
2814 
2815 	Ref<VisualShaderNodePluginDefault> default_plugin;
2816 	default_plugin.instance();
2817 	add_plugin(default_plugin);
2818 
2819 	property_editor = memnew(CustomPropertyEditor);
2820 	add_child(property_editor);
2821 
2822 	property_editor->connect("variant_changed", this, "_port_edited");
2823 }
2824 
edit(Object * p_object)2825 void VisualShaderEditorPlugin::edit(Object *p_object) {
2826 
2827 	visual_shader_editor->edit(Object::cast_to<VisualShader>(p_object));
2828 }
2829 
handles(Object * p_object) const2830 bool VisualShaderEditorPlugin::handles(Object *p_object) const {
2831 
2832 	return p_object->is_class("VisualShader");
2833 }
2834 
make_visible(bool p_visible)2835 void VisualShaderEditorPlugin::make_visible(bool p_visible) {
2836 
2837 	if (p_visible) {
2838 		//editor->hide_animation_player_editors();
2839 		//editor->animation_panel_make_visible(true);
2840 		button->show();
2841 		editor->make_bottom_panel_item_visible(visual_shader_editor);
2842 		visual_shader_editor->update_custom_nodes();
2843 		visual_shader_editor->set_process_input(true);
2844 		//visual_shader_editor->set_process(true);
2845 	} else {
2846 
2847 		if (visual_shader_editor->is_visible_in_tree())
2848 			editor->hide_bottom_panel();
2849 		button->hide();
2850 		visual_shader_editor->set_process_input(false);
2851 		//visual_shader_editor->set_process(false);
2852 	}
2853 }
2854 
VisualShaderEditorPlugin(EditorNode * p_node)2855 VisualShaderEditorPlugin::VisualShaderEditorPlugin(EditorNode *p_node) {
2856 
2857 	editor = p_node;
2858 	visual_shader_editor = memnew(VisualShaderEditor);
2859 	visual_shader_editor->set_custom_minimum_size(Size2(0, 300) * EDSCALE);
2860 
2861 	button = editor->add_bottom_panel_item(TTR("VisualShader"), visual_shader_editor);
2862 	button->hide();
2863 }
2864 
~VisualShaderEditorPlugin()2865 VisualShaderEditorPlugin::~VisualShaderEditorPlugin() {
2866 }
2867 
2868 ////////////////
2869 
2870 class VisualShaderNodePluginInputEditor : public OptionButton {
2871 	GDCLASS(VisualShaderNodePluginInputEditor, OptionButton);
2872 
2873 	Ref<VisualShaderNodeInput> input;
2874 
2875 protected:
_bind_methods()2876 	static void _bind_methods() {
2877 		ClassDB::bind_method("_item_selected", &VisualShaderNodePluginInputEditor::_item_selected);
2878 	}
2879 
2880 public:
_notification(int p_what)2881 	void _notification(int p_what) {
2882 		if (p_what == NOTIFICATION_READY) {
2883 			connect("item_selected", this, "_item_selected");
2884 		}
2885 	}
2886 
_item_selected(int p_item)2887 	void _item_selected(int p_item) {
2888 		VisualShaderEditor::get_singleton()->call_deferred("_input_select_item", input, get_item_text(p_item));
2889 	}
2890 
setup(const Ref<VisualShaderNodeInput> & p_input)2891 	void setup(const Ref<VisualShaderNodeInput> &p_input) {
2892 		input = p_input;
2893 		Ref<Texture> type_icon[5] = {
2894 			EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"),
2895 			EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons"),
2896 			EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons"),
2897 			EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"),
2898 			EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons"),
2899 		};
2900 
2901 		add_item("[None]");
2902 		int to_select = -1;
2903 		for (int i = 0; i < input->get_input_index_count(); i++) {
2904 			if (input->get_input_name() == input->get_input_index_name(i)) {
2905 				to_select = i + 1;
2906 			}
2907 			add_icon_item(type_icon[input->get_input_index_type(i)], input->get_input_index_name(i));
2908 		}
2909 
2910 		if (to_select >= 0) {
2911 			select(to_select);
2912 		}
2913 	}
2914 };
2915 
2916 class VisualShaderNodePluginDefaultEditor : public VBoxContainer {
2917 	GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer);
2918 	Ref<Resource> parent_resource;
2919 
2920 public:
_property_changed(const String & prop,const Variant & p_value,const String & p_field,bool p_changing=false)2921 	void _property_changed(const String &prop, const Variant &p_value, const String &p_field, bool p_changing = false) {
2922 
2923 		if (p_changing)
2924 			return;
2925 
2926 		UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
2927 
2928 		updating = true;
2929 		undo_redo->create_action(TTR("Edit Visual Property") + ": " + prop, UndoRedo::MERGE_ENDS);
2930 		undo_redo->add_do_property(node.ptr(), prop, p_value);
2931 		undo_redo->add_undo_property(node.ptr(), prop, node->get(prop));
2932 
2933 		if (p_value.get_type() == Variant::OBJECT) {
2934 
2935 			RES prev_res = node->get(prop);
2936 			RES curr_res = p_value;
2937 
2938 			if (curr_res.is_null()) {
2939 				undo_redo->add_do_method(this, "_open_inspector", (RES)parent_resource.ptr());
2940 			} else {
2941 				undo_redo->add_do_method(this, "_open_inspector", (RES)curr_res.ptr());
2942 			}
2943 			if (!prev_res.is_null()) {
2944 				undo_redo->add_undo_method(this, "_open_inspector", (RES)prev_res.ptr());
2945 			} else {
2946 				undo_redo->add_undo_method(this, "_open_inspector", (RES)parent_resource.ptr());
2947 			}
2948 			undo_redo->add_do_method(this, "_refresh_request");
2949 			undo_redo->add_undo_method(this, "_refresh_request");
2950 		}
2951 		undo_redo->commit_action();
2952 
2953 		updating = false;
2954 	}
2955 
_node_changed()2956 	void _node_changed() {
2957 		if (updating)
2958 			return;
2959 		for (int i = 0; i < properties.size(); i++) {
2960 			properties[i]->update_property();
2961 		}
2962 	}
2963 
_refresh_request()2964 	void _refresh_request() {
2965 		VisualShaderEditor::get_singleton()->call_deferred("_update_graph");
2966 	}
2967 
_resource_selected(const String & p_path,RES p_resource)2968 	void _resource_selected(const String &p_path, RES p_resource) {
2969 		_open_inspector(p_resource);
2970 	}
2971 
_open_inspector(RES p_resource)2972 	void _open_inspector(RES p_resource) {
2973 		EditorNode::get_singleton()->get_inspector()->edit(p_resource.ptr());
2974 	}
2975 
2976 	bool updating;
2977 	Ref<VisualShaderNode> node;
2978 	Vector<EditorProperty *> properties;
2979 
setup(Ref<Resource> p_parent_resource,Vector<EditorProperty * > p_properties,const Vector<StringName> & p_names,Ref<VisualShaderNode> p_node)2980 	void setup(Ref<Resource> p_parent_resource, Vector<EditorProperty *> p_properties, const Vector<StringName> &p_names, Ref<VisualShaderNode> p_node) {
2981 		parent_resource = p_parent_resource;
2982 		updating = false;
2983 		node = p_node;
2984 		properties = p_properties;
2985 
2986 		for (int i = 0; i < p_properties.size(); i++) {
2987 
2988 			add_child(p_properties[i]);
2989 
2990 			bool res_prop = Object::cast_to<EditorPropertyResource>(p_properties[i]);
2991 			if (res_prop) {
2992 				p_properties[i]->connect("resource_selected", this, "_resource_selected");
2993 			}
2994 
2995 			properties[i]->connect("property_changed", this, "_property_changed");
2996 			properties[i]->set_object_and_property(node.ptr(), p_names[i]);
2997 			properties[i]->update_property();
2998 			properties[i]->set_name_split_ratio(0);
2999 		}
3000 		node->connect("changed", this, "_node_changed");
3001 		node->connect("editor_refresh_request", this, "_refresh_request", varray(), CONNECT_DEFERRED);
3002 	}
3003 
_bind_methods()3004 	static void _bind_methods() {
3005 		ClassDB::bind_method("_property_changed", &VisualShaderNodePluginDefaultEditor::_property_changed, DEFVAL(String()), DEFVAL(false));
3006 		ClassDB::bind_method("_node_changed", &VisualShaderNodePluginDefaultEditor::_node_changed);
3007 		ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request);
3008 		ClassDB::bind_method("_resource_selected", &VisualShaderNodePluginDefaultEditor::_resource_selected);
3009 		ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector);
3010 	}
3011 };
3012 
create_editor(const Ref<Resource> & p_parent_resource,const Ref<VisualShaderNode> & p_node)3013 Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
3014 
3015 	if (p_node->is_class("VisualShaderNodeInput")) {
3016 		//create input
3017 		VisualShaderNodePluginInputEditor *input_editor = memnew(VisualShaderNodePluginInputEditor);
3018 		input_editor->setup(p_node);
3019 		return input_editor;
3020 	}
3021 
3022 	Vector<StringName> properties = p_node->get_editable_properties();
3023 	if (properties.size() == 0) {
3024 		return NULL;
3025 	}
3026 
3027 	List<PropertyInfo> props;
3028 	p_node->get_property_list(&props);
3029 
3030 	Vector<PropertyInfo> pinfo;
3031 
3032 	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
3033 
3034 		for (int i = 0; i < properties.size(); i++) {
3035 			if (E->get().name == String(properties[i])) {
3036 				pinfo.push_back(E->get());
3037 			}
3038 		}
3039 	}
3040 
3041 	if (pinfo.size() == 0)
3042 		return NULL;
3043 
3044 	properties.clear();
3045 
3046 	Ref<VisualShaderNode> node = p_node;
3047 	Vector<EditorProperty *> editors;
3048 
3049 	for (int i = 0; i < pinfo.size(); i++) {
3050 
3051 		EditorProperty *prop = EditorInspector::instantiate_property_editor(node.ptr(), pinfo[i].type, pinfo[i].name, pinfo[i].hint, pinfo[i].hint_string, pinfo[i].usage);
3052 		if (!prop)
3053 			return NULL;
3054 
3055 		if (Object::cast_to<EditorPropertyResource>(prop)) {
3056 			Object::cast_to<EditorPropertyResource>(prop)->set_use_sub_inspector(false);
3057 			prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
3058 		} else if (Object::cast_to<EditorPropertyTransform>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
3059 			prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
3060 		} else if (Object::cast_to<EditorPropertyFloat>(prop)) {
3061 			prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
3062 		} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
3063 			prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
3064 			Object::cast_to<EditorPropertyEnum>(prop)->set_option_button_clip(false);
3065 		}
3066 
3067 		editors.push_back(prop);
3068 		properties.push_back(pinfo[i].name);
3069 	}
3070 	VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor);
3071 	editor->setup(p_parent_resource, editors, properties, p_node);
3072 	return editor;
3073 }
3074 
_option_selected(int p_which)3075 void EditorPropertyShaderMode::_option_selected(int p_which) {
3076 
3077 	//will not use this, instead will do all the logic setting manually
3078 	//emit_signal("property_changed", get_edited_property(), p_which);
3079 
3080 	Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
3081 
3082 	if (visual_shader->get_mode() == p_which)
3083 		return;
3084 
3085 	UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
3086 	undo_redo->create_action(TTR("Visual Shader Mode Changed"));
3087 	//do is easy
3088 	undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which);
3089 	undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode());
3090 	//now undo is hell
3091 
3092 	//1. restore connections to output
3093 	for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
3094 
3095 		VisualShader::Type type = VisualShader::Type(i);
3096 		List<VisualShader::Connection> conns;
3097 		visual_shader->get_node_connections(type, &conns);
3098 		for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
3099 			if (E->get().to_node == VisualShader::NODE_ID_OUTPUT) {
3100 				undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
3101 			}
3102 		}
3103 	}
3104 	//2. restore input indices
3105 	for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
3106 
3107 		VisualShader::Type type = VisualShader::Type(i);
3108 		Vector<int> nodes = visual_shader->get_node_list(type);
3109 		for (int j = 0; j < nodes.size(); j++) {
3110 			Ref<VisualShaderNodeInput> input = visual_shader->get_node(type, nodes[j]);
3111 			if (!input.is_valid()) {
3112 				continue;
3113 			}
3114 
3115 			undo_redo->add_undo_method(input.ptr(), "set_input_name", input->get_input_name());
3116 		}
3117 	}
3118 
3119 	//3. restore enums and flags
3120 	List<PropertyInfo> props;
3121 	visual_shader->get_property_list(&props);
3122 
3123 	for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
3124 
3125 		if (E->get().name.begins_with("flags/") || E->get().name.begins_with("modes/")) {
3126 			undo_redo->add_undo_property(visual_shader.ptr(), E->get().name, visual_shader->get(E->get().name));
3127 		}
3128 	}
3129 
3130 	undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_options_menu");
3131 	undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_options_menu");
3132 
3133 	//update graph
3134 	undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_update_graph");
3135 	undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_update_graph");
3136 
3137 	undo_redo->commit_action();
3138 }
3139 
update_property()3140 void EditorPropertyShaderMode::update_property() {
3141 
3142 	int which = get_edited_object()->get(get_edited_property());
3143 	options->select(which);
3144 }
3145 
setup(const Vector<String> & p_options)3146 void EditorPropertyShaderMode::setup(const Vector<String> &p_options) {
3147 	for (int i = 0; i < p_options.size(); i++) {
3148 		options->add_item(p_options[i], i);
3149 	}
3150 }
3151 
set_option_button_clip(bool p_enable)3152 void EditorPropertyShaderMode::set_option_button_clip(bool p_enable) {
3153 	options->set_clip_text(p_enable);
3154 }
3155 
_bind_methods()3156 void EditorPropertyShaderMode::_bind_methods() {
3157 
3158 	ClassDB::bind_method(D_METHOD("_option_selected"), &EditorPropertyShaderMode::_option_selected);
3159 }
3160 
EditorPropertyShaderMode()3161 EditorPropertyShaderMode::EditorPropertyShaderMode() {
3162 	options = memnew(OptionButton);
3163 	options->set_clip_text(true);
3164 	add_child(options);
3165 	add_focusable(options);
3166 	options->connect("item_selected", this, "_option_selected");
3167 }
3168 
can_handle(Object * p_object)3169 bool EditorInspectorShaderModePlugin::can_handle(Object *p_object) {
3170 	return true; //can handle everything
3171 }
3172 
parse_begin(Object * p_object)3173 void EditorInspectorShaderModePlugin::parse_begin(Object *p_object) {
3174 	//do none
3175 }
3176 
parse_property(Object * p_object,Variant::Type p_type,const String & p_path,PropertyHint p_hint,const String & p_hint_text,int p_usage)3177 bool EditorInspectorShaderModePlugin::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage) {
3178 
3179 	if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
3180 
3181 		EditorPropertyShaderMode *editor = memnew(EditorPropertyShaderMode);
3182 		Vector<String> options = p_hint_text.split(",");
3183 		editor->setup(options);
3184 		add_property_editor(p_path, editor);
3185 
3186 		return true;
3187 	}
3188 
3189 	return false; //can be overridden, although it will most likely be last anyway
3190 }
3191 
parse_end()3192 void EditorInspectorShaderModePlugin::parse_end() {
3193 	//do none
3194 }
3195 //////////////////////////////////
3196 
_shader_changed()3197 void VisualShaderNodePortPreview::_shader_changed() {
3198 	if (shader.is_null()) {
3199 		return;
3200 	}
3201 
3202 	Vector<VisualShader::DefaultTextureParam> default_textures;
3203 	String shader_code = shader->generate_preview_shader(type, node, port, default_textures);
3204 
3205 	Ref<Shader> preview_shader;
3206 	preview_shader.instance();
3207 	preview_shader->set_code(shader_code);
3208 	for (int i = 0; i < default_textures.size(); i++) {
3209 		preview_shader->set_default_texture_param(default_textures[i].name, default_textures[i].param);
3210 	}
3211 
3212 	Ref<ShaderMaterial> material;
3213 	material.instance();
3214 	material->set_shader(preview_shader);
3215 
3216 	//find if a material is also being edited and copy parameters to this one
3217 
3218 	for (int i = EditorNode::get_singleton()->get_editor_history()->get_path_size() - 1; i >= 0; i--) {
3219 		Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_history()->get_path_object(i));
3220 		if (!object)
3221 			continue;
3222 		ShaderMaterial *src_mat = Object::cast_to<ShaderMaterial>(object);
3223 		if (src_mat && src_mat->get_shader().is_valid()) {
3224 
3225 			List<PropertyInfo> params;
3226 			src_mat->get_shader()->get_param_list(&params);
3227 			for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
3228 				material->set(E->get().name, src_mat->get(E->get().name));
3229 			}
3230 		}
3231 	}
3232 
3233 	set_material(material);
3234 }
3235 
setup(const Ref<VisualShader> & p_shader,VisualShader::Type p_type,int p_node,int p_port)3236 void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, VisualShader::Type p_type, int p_node, int p_port) {
3237 
3238 	shader = p_shader;
3239 	shader->connect("changed", this, "_shader_changed");
3240 	type = p_type;
3241 	port = p_port;
3242 	node = p_node;
3243 	update();
3244 	_shader_changed();
3245 }
3246 
get_minimum_size() const3247 Size2 VisualShaderNodePortPreview::get_minimum_size() const {
3248 	return Size2(100, 100) * EDSCALE;
3249 }
3250 
_notification(int p_what)3251 void VisualShaderNodePortPreview::_notification(int p_what) {
3252 	if (p_what == NOTIFICATION_DRAW) {
3253 		Vector<Vector2> points;
3254 		Vector<Vector2> uvs;
3255 		Vector<Color> colors;
3256 		points.push_back(Vector2());
3257 		uvs.push_back(Vector2(0, 0));
3258 		colors.push_back(Color(1, 1, 1, 1));
3259 		points.push_back(Vector2(get_size().width, 0));
3260 		uvs.push_back(Vector2(1, 0));
3261 		colors.push_back(Color(1, 1, 1, 1));
3262 		points.push_back(get_size());
3263 		uvs.push_back(Vector2(1, 1));
3264 		colors.push_back(Color(1, 1, 1, 1));
3265 		points.push_back(Vector2(0, get_size().height));
3266 		uvs.push_back(Vector2(0, 1));
3267 		colors.push_back(Color(1, 1, 1, 1));
3268 
3269 		draw_primitive(points, colors, uvs);
3270 	}
3271 }
3272 
_bind_methods()3273 void VisualShaderNodePortPreview::_bind_methods() {
3274 	ClassDB::bind_method("_shader_changed", &VisualShaderNodePortPreview::_shader_changed);
3275 }
3276 
VisualShaderNodePortPreview()3277 VisualShaderNodePortPreview::VisualShaderNodePortPreview() {
3278 }
3279 
3280 //////////////////////////////////
3281 
converts_to() const3282 String VisualShaderConversionPlugin::converts_to() const {
3283 
3284 	return "Shader";
3285 }
3286 
handles(const Ref<Resource> & p_resource) const3287 bool VisualShaderConversionPlugin::handles(const Ref<Resource> &p_resource) const {
3288 
3289 	Ref<VisualShader> vshader = p_resource;
3290 	return vshader.is_valid();
3291 }
3292 
convert(const Ref<Resource> & p_resource) const3293 Ref<Resource> VisualShaderConversionPlugin::convert(const Ref<Resource> &p_resource) const {
3294 
3295 	Ref<VisualShader> vshader = p_resource;
3296 	ERR_FAIL_COND_V(!vshader.is_valid(), Ref<Resource>());
3297 
3298 	Ref<Shader> shader;
3299 	shader.instance();
3300 
3301 	String code = vshader->get_code();
3302 	shader->set_code(code);
3303 
3304 	return shader;
3305 }
3306