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(¶ms);
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