1/**************************************************************************/
2/* visual_shader.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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.h"
32
33#include "core/templates/rb_map.h"
34#include "core/templates/vmap.h"
35#include "servers/rendering/shader_types.h"
36#include "visual_shader_nodes.h"
37#include "visual_shader_particle_nodes.h"
38#include "visual_shader_sdf_nodes.h"
39
40String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) {
41 static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
42 return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id);
43}
44
45bool VisualShaderNode::is_simple_decl() const {
46 return simple_decl;
47}
48
49int VisualShaderNode::get_default_input_port(PortType p_type) const {
50 return 0;
51}
52
53void VisualShaderNode::set_output_port_for_preview(int p_index) {
54 port_preview = p_index;
55}
56
57int VisualShaderNode::get_output_port_for_preview() const {
58 return port_preview;
59}
60
61void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) {
62 Variant value = p_value;
63
64 if (p_prev_value.get_type() != Variant::NIL) {
65 switch (p_value.get_type()) {
66 case Variant::FLOAT: {
67 switch (p_prev_value.get_type()) {
68 case Variant::INT: {
69 value = (float)p_prev_value;
70 } break;
71 case Variant::FLOAT: {
72 value = p_prev_value;
73 } break;
74 case Variant::VECTOR2: {
75 Vector2 pv = p_prev_value;
76 value = pv.x;
77 } break;
78 case Variant::VECTOR3: {
79 Vector3 pv = p_prev_value;
80 value = pv.x;
81 } break;
82 case Variant::QUATERNION: {
83 Quaternion pv = p_prev_value;
84 value = pv.x;
85 } break;
86 default:
87 break;
88 }
89 } break;
90 case Variant::INT: {
91 switch (p_prev_value.get_type()) {
92 case Variant::INT: {
93 value = p_prev_value;
94 } break;
95 case Variant::FLOAT: {
96 value = (int)p_prev_value;
97 } break;
98 case Variant::VECTOR2: {
99 Vector2 pv = p_prev_value;
100 value = (int)pv.x;
101 } break;
102 case Variant::VECTOR3: {
103 Vector3 pv = p_prev_value;
104 value = (int)pv.x;
105 } break;
106 case Variant::QUATERNION: {
107 Quaternion pv = p_prev_value;
108 value = (int)pv.x;
109 } break;
110 default:
111 break;
112 }
113 } break;
114 case Variant::VECTOR2: {
115 switch (p_prev_value.get_type()) {
116 case Variant::INT: {
117 float pv = (float)(int)p_prev_value;
118 value = Vector2(pv, pv);
119 } break;
120 case Variant::FLOAT: {
121 float pv = p_prev_value;
122 value = Vector2(pv, pv);
123 } break;
124 case Variant::VECTOR2: {
125 value = p_prev_value;
126 } break;
127 case Variant::VECTOR3: {
128 Vector3 pv = p_prev_value;
129 value = Vector2(pv.x, pv.y);
130 } break;
131 case Variant::QUATERNION: {
132 Quaternion pv = p_prev_value;
133 value = Vector2(pv.x, pv.y);
134 } break;
135 default:
136 break;
137 }
138 } break;
139 case Variant::VECTOR3: {
140 switch (p_prev_value.get_type()) {
141 case Variant::INT: {
142 float pv = (float)(int)p_prev_value;
143 value = Vector3(pv, pv, pv);
144 } break;
145 case Variant::FLOAT: {
146 float pv = p_prev_value;
147 value = Vector3(pv, pv, pv);
148 } break;
149 case Variant::VECTOR2: {
150 Vector2 pv = p_prev_value;
151 value = Vector3(pv.x, pv.y, pv.y);
152 } break;
153 case Variant::VECTOR3: {
154 value = p_prev_value;
155 } break;
156 case Variant::QUATERNION: {
157 Quaternion pv = p_prev_value;
158 value = Vector3(pv.x, pv.y, pv.z);
159 } break;
160 default:
161 break;
162 }
163 } break;
164 case Variant::QUATERNION: {
165 switch (p_prev_value.get_type()) {
166 case Variant::INT: {
167 float pv = (float)(int)p_prev_value;
168 value = Quaternion(pv, pv, pv, pv);
169 } break;
170 case Variant::FLOAT: {
171 float pv = p_prev_value;
172 value = Quaternion(pv, pv, pv, pv);
173 } break;
174 case Variant::VECTOR2: {
175 Vector2 pv = p_prev_value;
176 value = Quaternion(pv.x, pv.y, pv.y, pv.y);
177 } break;
178 case Variant::VECTOR3: {
179 Vector3 pv = p_prev_value;
180 value = Quaternion(pv.x, pv.y, pv.z, pv.z);
181 } break;
182 case Variant::QUATERNION: {
183 value = p_prev_value;
184 } break;
185 default:
186 break;
187 }
188 } break;
189 default:
190 break;
191 }
192 }
193 default_input_values[p_port] = value;
194 emit_changed();
195}
196
197Variant VisualShaderNode::get_input_port_default_value(int p_port) const {
198 if (default_input_values.has(p_port)) {
199 return default_input_values[p_port];
200 }
201
202 return Variant();
203}
204
205void VisualShaderNode::remove_input_port_default_value(int p_port) {
206 if (default_input_values.has(p_port)) {
207 default_input_values.erase(p_port);
208 emit_changed();
209 }
210}
211
212void VisualShaderNode::clear_default_input_values() {
213 if (!default_input_values.is_empty()) {
214 default_input_values.clear();
215 emit_changed();
216 }
217}
218
219bool VisualShaderNode::is_port_separator(int p_index) const {
220 return false;
221}
222
223bool VisualShaderNode::is_output_port_connected(int p_port) const {
224 if (connected_output_ports.has(p_port)) {
225 return connected_output_ports[p_port] > 0;
226 }
227 return false;
228}
229
230void VisualShaderNode::set_output_port_connected(int p_port, bool p_connected) {
231 if (p_connected) {
232 connected_output_ports[p_port]++;
233 } else {
234 connected_output_ports[p_port]--;
235 }
236}
237
238bool VisualShaderNode::is_input_port_connected(int p_port) const {
239 if (connected_input_ports.has(p_port)) {
240 return connected_input_ports[p_port];
241 }
242 return false;
243}
244
245void VisualShaderNode::set_input_port_connected(int p_port, bool p_connected) {
246 connected_input_ports[p_port] = p_connected;
247}
248
249bool VisualShaderNode::is_generate_input_var(int p_port) const {
250 return true;
251}
252
253bool VisualShaderNode::is_output_port_expandable(int p_port) const {
254 return false;
255}
256
257bool VisualShaderNode::has_output_port_preview(int p_port) const {
258 return true;
259}
260
261void VisualShaderNode::_set_output_ports_expanded(const Array &p_values) {
262 for (int i = 0; i < p_values.size(); i++) {
263 expanded_output_ports[p_values[i]] = true;
264 }
265 emit_changed();
266}
267
268Array VisualShaderNode::_get_output_ports_expanded() const {
269 Array arr;
270 for (int i = 0; i < get_output_port_count(); i++) {
271 if (_is_output_port_expanded(i)) {
272 arr.push_back(i);
273 }
274 }
275 return arr;
276}
277
278void VisualShaderNode::_set_output_port_expanded(int p_port, bool p_expanded) {
279 expanded_output_ports[p_port] = p_expanded;
280 emit_changed();
281}
282
283bool VisualShaderNode::_is_output_port_expanded(int p_port) const {
284 if (expanded_output_ports.has(p_port)) {
285 return expanded_output_ports[p_port];
286 }
287 return false;
288}
289
290int VisualShaderNode::get_expanded_output_port_count() const {
291 int count = get_output_port_count();
292 int count2 = count;
293 for (int i = 0; i < count; i++) {
294 if (is_output_port_expandable(i) && _is_output_port_expanded(i)) {
295 switch (get_output_port_type(i)) {
296 case PORT_TYPE_VECTOR_2D: {
297 count2 += 2;
298 } break;
299 case PORT_TYPE_VECTOR_3D: {
300 count2 += 3;
301 } break;
302 case PORT_TYPE_VECTOR_4D: {
303 count2 += 4;
304 } break;
305 default:
306 break;
307 }
308 }
309 }
310 return count2;
311}
312
313bool VisualShaderNode::is_code_generated() const {
314 return true;
315}
316
317bool VisualShaderNode::is_show_prop_names() const {
318 return false;
319}
320
321bool VisualShaderNode::is_use_prop_slots() const {
322 return false;
323}
324
325bool VisualShaderNode::is_disabled() const {
326 return disabled;
327}
328
329void VisualShaderNode::set_disabled(bool p_disabled) {
330 disabled = p_disabled;
331}
332
333bool VisualShaderNode::is_closable() const {
334 return closable;
335}
336
337void VisualShaderNode::set_closable(bool p_closable) {
338 closable = p_closable;
339}
340
341Vector<VisualShader::DefaultTextureParam> VisualShaderNode::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const {
342 return Vector<VisualShader::DefaultTextureParam>();
343}
344
345String VisualShaderNode::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
346 return String();
347}
348
349String VisualShaderNode::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
350 return String();
351}
352
353String VisualShaderNode::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
354 return String();
355}
356
357Vector<StringName> VisualShaderNode::get_editable_properties() const {
358 return Vector<StringName>();
359}
360
361HashMap<StringName, String> VisualShaderNode::get_editable_properties_names() const {
362 return HashMap<StringName, String>();
363}
364
365Array VisualShaderNode::get_default_input_values() const {
366 Array ret;
367 for (const KeyValue<int, Variant> &E : default_input_values) {
368 ret.push_back(E.key);
369 ret.push_back(E.value);
370 }
371 return ret;
372}
373
374void VisualShaderNode::set_default_input_values(const Array &p_values) {
375 if (p_values.size() % 2 == 0) {
376 for (int i = 0; i < p_values.size(); i += 2) {
377 default_input_values[p_values[i + 0]] = p_values[i + 1];
378 }
379 }
380
381 emit_changed();
382}
383
384String VisualShaderNode::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
385 return String();
386}
387
388bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const {
389 return false;
390}
391
392void VisualShaderNode::_bind_methods() {
393 ClassDB::bind_method(D_METHOD("get_default_input_port", "type"), &VisualShaderNode::get_default_input_port);
394
395 ClassDB::bind_method(D_METHOD("set_output_port_for_preview", "port"), &VisualShaderNode::set_output_port_for_preview);
396 ClassDB::bind_method(D_METHOD("get_output_port_for_preview"), &VisualShaderNode::get_output_port_for_preview);
397
398 ClassDB::bind_method(D_METHOD("_set_output_port_expanded", "port"), &VisualShaderNode::_set_output_port_expanded);
399 ClassDB::bind_method(D_METHOD("_is_output_port_expanded"), &VisualShaderNode::_is_output_port_expanded);
400
401 ClassDB::bind_method(D_METHOD("_set_output_ports_expanded", "values"), &VisualShaderNode::_set_output_ports_expanded);
402 ClassDB::bind_method(D_METHOD("_get_output_ports_expanded"), &VisualShaderNode::_get_output_ports_expanded);
403
404 ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value", "prev_value"), &VisualShaderNode::set_input_port_default_value, DEFVAL(Variant()));
405 ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
406
407 ClassDB::bind_method(D_METHOD("remove_input_port_default_value", "port"), &VisualShaderNode::remove_input_port_default_value);
408 ClassDB::bind_method(D_METHOD("clear_default_input_values"), &VisualShaderNode::clear_default_input_values);
409
410 ClassDB::bind_method(D_METHOD("set_default_input_values", "values"), &VisualShaderNode::set_default_input_values);
411 ClassDB::bind_method(D_METHOD("get_default_input_values"), &VisualShaderNode::get_default_input_values);
412
413 ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
414 ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
415 ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
416
417 BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
418 BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT);
419 BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_UINT);
420 BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_2D);
421 BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_3D);
422 BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_4D);
423 BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN);
424 BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM);
425 BIND_ENUM_CONSTANT(PORT_TYPE_SAMPLER);
426 BIND_ENUM_CONSTANT(PORT_TYPE_MAX);
427}
428
429VisualShaderNode::VisualShaderNode() {
430}
431
432/////////////////////////////////////////////////////////
433
434void VisualShaderNodeCustom::update_ports() {
435 {
436 input_ports.clear();
437 int input_port_count;
438 if (GDVIRTUAL_CALL(_get_input_port_count, input_port_count)) {
439 for (int i = 0; i < input_port_count; i++) {
440 Port port;
441 if (!GDVIRTUAL_CALL(_get_input_port_name, i, port.name)) {
442 port.name = "in" + itos(i);
443 }
444 PortType port_type;
445 if (GDVIRTUAL_CALL(_get_input_port_type, i, port_type)) {
446 port.type = (int)port_type;
447 } else {
448 port.type = (int)PortType::PORT_TYPE_SCALAR;
449 }
450
451 input_ports.push_back(port);
452 }
453 }
454 }
455
456 {
457 output_ports.clear();
458 int output_port_count;
459 if (GDVIRTUAL_CALL(_get_output_port_count, output_port_count)) {
460 for (int i = 0; i < output_port_count; i++) {
461 Port port;
462 if (!GDVIRTUAL_CALL(_get_output_port_name, i, port.name)) {
463 port.name = "out" + itos(i);
464 }
465 PortType port_type;
466 if (GDVIRTUAL_CALL(_get_output_port_type, i, port_type)) {
467 port.type = (int)port_type;
468 } else {
469 port.type = (int)PortType::PORT_TYPE_SCALAR;
470 }
471
472 output_ports.push_back(port);
473 }
474 }
475 }
476}
477
478String VisualShaderNodeCustom::get_caption() const {
479 String ret = "Unnamed";
480 GDVIRTUAL_CALL(_get_name, ret);
481 return ret;
482}
483
484int VisualShaderNodeCustom::get_input_port_count() const {
485 return input_ports.size();
486}
487
488VisualShaderNodeCustom::PortType VisualShaderNodeCustom::get_input_port_type(int p_port) const {
489 ERR_FAIL_INDEX_V(p_port, input_ports.size(), PORT_TYPE_SCALAR);
490 return (PortType)input_ports[p_port].type;
491}
492
493String VisualShaderNodeCustom::get_input_port_name(int p_port) const {
494 ERR_FAIL_INDEX_V(p_port, input_ports.size(), "");
495 return input_ports[p_port].name;
496}
497
498int VisualShaderNodeCustom::get_default_input_port(PortType p_type) const {
499 int ret = 0;
500 GDVIRTUAL_CALL(_get_default_input_port, p_type, ret);
501 return ret;
502}
503
504int VisualShaderNodeCustom::get_output_port_count() const {
505 return output_ports.size();
506}
507
508VisualShaderNodeCustom::PortType VisualShaderNodeCustom::get_output_port_type(int p_port) const {
509 ERR_FAIL_INDEX_V(p_port, output_ports.size(), PORT_TYPE_SCALAR);
510 return (PortType)output_ports[p_port].type;
511}
512
513String VisualShaderNodeCustom::get_output_port_name(int p_port) const {
514 ERR_FAIL_INDEX_V(p_port, output_ports.size(), "");
515 return output_ports[p_port].name;
516}
517
518String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
519 ERR_FAIL_COND_V(!GDVIRTUAL_IS_OVERRIDDEN(_get_code), "");
520 TypedArray<String> input_vars;
521 for (int i = 0; i < get_input_port_count(); i++) {
522 input_vars.push_back(p_input_vars[i]);
523 }
524 TypedArray<String> output_vars;
525 for (int i = 0; i < get_output_port_count(); i++) {
526 output_vars.push_back(p_output_vars[i]);
527 }
528
529 String _code;
530 GDVIRTUAL_CALL(_get_code, input_vars, output_vars, p_mode, p_type, _code);
531 if (_is_valid_code(_code)) {
532 String code = " {\n";
533 bool nend = _code.ends_with("\n");
534 _code = _code.insert(0, " ");
535 _code = _code.replace("\n", "\n ");
536 code += _code;
537 if (!nend) {
538 code += "\n }";
539 } else {
540 code.remove_at(code.size() - 1);
541 code += "}";
542 }
543 code += "\n";
544 return code;
545 }
546 return String();
547}
548
549String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
550 String _code;
551 if (GDVIRTUAL_CALL(_get_global_code, p_mode, _code)) {
552 if (_is_valid_code(_code)) {
553 String code = "// " + get_caption() + "\n";
554 code += _code;
555 code += "\n";
556 return code;
557 }
558 }
559 return String();
560}
561
562String VisualShaderNodeCustom::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
563 String _code;
564 if (GDVIRTUAL_CALL(_get_func_code, p_mode, p_type, _code)) {
565 if (_is_valid_code(_code)) {
566 bool nend = _code.ends_with("\n");
567 String code = "// " + get_caption() + "\n";
568 code += " {\n";
569 _code = _code.insert(0, " ");
570 _code = _code.replace("\n", "\n ");
571 code += _code;
572 if (!nend) {
573 code += "\n }";
574 } else {
575 code.remove_at(code.size() - 1);
576 code += "}";
577 }
578 code += "\n";
579 return code;
580 }
581 }
582 return String();
583}
584
585bool VisualShaderNodeCustom::is_available(Shader::Mode p_mode, VisualShader::Type p_type) const {
586 bool ret = true;
587 GDVIRTUAL_CALL(_is_available, p_mode, p_type, ret);
588 return ret;
589}
590
591void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) {
592 if (!is_initialized) {
593 VisualShaderNode::set_input_port_default_value(p_port, p_value, p_prev_value);
594 }
595}
596
597void VisualShaderNodeCustom::set_default_input_values(const Array &p_values) {
598 if (!is_initialized) {
599 VisualShaderNode::set_default_input_values(p_values);
600 }
601}
602
603void VisualShaderNodeCustom::remove_input_port_default_value(int p_port) {
604 if (!is_initialized) {
605 VisualShaderNode::remove_input_port_default_value(p_port);
606 }
607}
608
609void VisualShaderNodeCustom::clear_default_input_values() {
610 if (!is_initialized) {
611 VisualShaderNode::clear_default_input_values();
612 }
613}
614
615void VisualShaderNodeCustom::_set_input_port_default_value(int p_port, const Variant &p_value) {
616 VisualShaderNode::set_input_port_default_value(p_port, p_value);
617}
618
619bool VisualShaderNodeCustom::_is_valid_code(const String &p_code) const {
620 if (p_code.is_empty() || p_code == "null") {
621 return false;
622 }
623 return true;
624}
625
626bool VisualShaderNodeCustom::_is_initialized() {
627 return is_initialized;
628}
629
630void VisualShaderNodeCustom::_set_initialized(bool p_enabled) {
631 is_initialized = p_enabled;
632}
633
634String VisualShaderNodeCustom::_get_name() const {
635 String ret;
636 GDVIRTUAL_CALL(_get_name, ret);
637 return ret;
638}
639
640String VisualShaderNodeCustom::_get_description() const {
641 String ret;
642 GDVIRTUAL_CALL(_get_description, ret);
643 return ret;
644}
645
646String VisualShaderNodeCustom::_get_category() const {
647 String ret;
648 GDVIRTUAL_CALL(_get_category, ret);
649 return ret;
650}
651
652VisualShaderNodeCustom::PortType VisualShaderNodeCustom::_get_return_icon_type() const {
653 PortType ret = PORT_TYPE_SCALAR;
654 GDVIRTUAL_CALL(_get_return_icon_type, ret);
655 return ret;
656}
657
658bool VisualShaderNodeCustom::_is_highend() const {
659 bool ret = false;
660 GDVIRTUAL_CALL(_is_highend, ret);
661 return ret;
662}
663
664void VisualShaderNodeCustom::_bind_methods() {
665 GDVIRTUAL_BIND(_get_name);
666 GDVIRTUAL_BIND(_get_description);
667 GDVIRTUAL_BIND(_get_category);
668 GDVIRTUAL_BIND(_get_return_icon_type);
669 GDVIRTUAL_BIND(_get_input_port_count);
670 GDVIRTUAL_BIND(_get_input_port_type, "port");
671 GDVIRTUAL_BIND(_get_input_port_name, "port");
672 GDVIRTUAL_BIND(_get_default_input_port, "type");
673 GDVIRTUAL_BIND(_get_output_port_count);
674 GDVIRTUAL_BIND(_get_output_port_type, "port");
675 GDVIRTUAL_BIND(_get_output_port_name, "port");
676 GDVIRTUAL_BIND(_get_code, "input_vars", "output_vars", "mode", "type");
677 GDVIRTUAL_BIND(_get_func_code, "mode", "type");
678 GDVIRTUAL_BIND(_get_global_code, "mode");
679 GDVIRTUAL_BIND(_is_highend);
680 GDVIRTUAL_BIND(_is_available, "mode", "type");
681
682 ClassDB::bind_method(D_METHOD("_set_initialized", "enabled"), &VisualShaderNodeCustom::_set_initialized);
683 ClassDB::bind_method(D_METHOD("_is_initialized"), &VisualShaderNodeCustom::_is_initialized);
684 ClassDB::bind_method(D_METHOD("_set_input_port_default_value", "port", "value"), &VisualShaderNodeCustom::_set_input_port_default_value);
685
686 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "initialized", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_initialized", "_is_initialized");
687}
688
689VisualShaderNodeCustom::VisualShaderNodeCustom() {
690 simple_decl = false;
691}
692
693/////////////////////////////////////////////////////////
694
695void VisualShader::set_shader_type(Type p_type) {
696 current_type = p_type;
697}
698
699VisualShader::Type VisualShader::get_shader_type() const {
700 return current_type;
701}
702
703void VisualShader::add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type) {
704 ERR_FAIL_COND(!p_name.is_valid_identifier());
705 ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
706 ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
707 ERR_FAIL_COND(varyings.has(p_name));
708 Varying var = Varying(p_name, p_mode, p_type);
709 varyings[p_name] = var;
710 varyings_list.push_back(var);
711 _queue_update();
712}
713
714void VisualShader::remove_varying(const String &p_name) {
715 ERR_FAIL_COND(!varyings.has(p_name));
716 varyings.erase(p_name);
717 for (List<Varying>::Element *E = varyings_list.front(); E; E = E->next()) {
718 if (E->get().name == p_name) {
719 varyings_list.erase(E);
720 break;
721 }
722 }
723 _queue_update();
724}
725
726bool VisualShader::has_varying(const String &p_name) const {
727 return varyings.has(p_name);
728}
729
730int VisualShader::get_varyings_count() const {
731 return varyings_list.size();
732}
733
734const VisualShader::Varying *VisualShader::get_varying_by_index(int p_idx) const {
735 ERR_FAIL_INDEX_V(p_idx, varyings_list.size(), nullptr);
736 return &varyings_list[p_idx];
737}
738
739void VisualShader::set_varying_mode(const String &p_name, VaryingMode p_mode) {
740 ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
741 ERR_FAIL_COND(!varyings.has(p_name));
742 if (varyings[p_name].mode == p_mode) {
743 return;
744 }
745 varyings[p_name].mode = p_mode;
746 _queue_update();
747}
748
749VisualShader::VaryingMode VisualShader::get_varying_mode(const String &p_name) {
750 ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_MODE_MAX);
751 return varyings[p_name].mode;
752}
753
754void VisualShader::set_varying_type(const String &p_name, VaryingType p_type) {
755 ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
756 ERR_FAIL_COND(!varyings.has(p_name));
757 if (varyings[p_name].type == p_type) {
758 return;
759 }
760 varyings[p_name].type = p_type;
761 _queue_update();
762}
763
764VisualShader::VaryingType VisualShader::get_varying_type(const String &p_name) {
765 ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_TYPE_MAX);
766 return varyings[p_name].type;
767}
768
769void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, const Vector2 &p_position, int p_id) {
770 ERR_FAIL_COND(p_node.is_null());
771 ERR_FAIL_COND(p_id < 2);
772 ERR_FAIL_INDEX(p_type, TYPE_MAX);
773 Graph *g = &graph[p_type];
774 ERR_FAIL_COND(g->nodes.has(p_id));
775 Node n;
776 n.node = p_node;
777 n.position = p_position;
778
779 Ref<VisualShaderNodeParameter> parameter = n.node;
780 if (parameter.is_valid()) {
781 String valid_name = validate_parameter_name(parameter->get_parameter_name(), parameter);
782 parameter->set_parameter_name(valid_name);
783 }
784
785 Ref<VisualShaderNodeInput> input = n.node;
786 if (input.is_valid()) {
787 input->shader_mode = shader_mode;
788 input->shader_type = p_type;
789 }
790
791 n.node->connect_changed(callable_mp(this, &VisualShader::_queue_update));
792
793 Ref<VisualShaderNodeCustom> custom = n.node;
794 if (custom.is_valid()) {
795 custom->update_ports();
796 }
797
798 g->nodes[p_id] = n;
799
800 _queue_update();
801}
802
803void VisualShader::set_node_position(Type p_type, int p_id, const Vector2 &p_position) {
804 ERR_FAIL_INDEX(p_type, TYPE_MAX);
805 Graph *g = &graph[p_type];
806 ERR_FAIL_COND(!g->nodes.has(p_id));
807 g->nodes[p_id].position = p_position;
808}
809
810Vector2 VisualShader::get_node_position(Type p_type, int p_id) const {
811 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Vector2());
812 const Graph *g = &graph[p_type];
813 ERR_FAIL_COND_V(!g->nodes.has(p_id), Vector2());
814 return g->nodes[p_id].position;
815}
816
817Ref<VisualShaderNode> VisualShader::get_node(Type p_type, int p_id) const {
818 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Ref<VisualShaderNode>());
819 const Graph *g = &graph[p_type];
820 ERR_FAIL_COND_V(!g->nodes.has(p_id), Ref<VisualShaderNode>());
821 return g->nodes[p_id].node;
822}
823
824Vector<int> VisualShader::get_node_list(Type p_type) const {
825 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Vector<int>());
826 const Graph *g = &graph[p_type];
827
828 Vector<int> ret;
829 for (const KeyValue<int, Node> &E : g->nodes) {
830 ret.push_back(E.key);
831 }
832
833 return ret;
834}
835
836int VisualShader::get_valid_node_id(Type p_type) const {
837 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, NODE_ID_INVALID);
838 const Graph *g = &graph[p_type];
839 return g->nodes.size() ? MAX(2, g->nodes.back()->key() + 1) : 2;
840}
841
842int VisualShader::find_node_id(Type p_type, const Ref<VisualShaderNode> &p_node) const {
843 for (const KeyValue<int, Node> &E : graph[p_type].nodes) {
844 if (E.value.node == p_node) {
845 return E.key;
846 }
847 }
848
849 return NODE_ID_INVALID;
850}
851
852void VisualShader::remove_node(Type p_type, int p_id) {
853 ERR_FAIL_INDEX(p_type, TYPE_MAX);
854 ERR_FAIL_COND(p_id < 2);
855 Graph *g = &graph[p_type];
856 ERR_FAIL_COND(!g->nodes.has(p_id));
857
858 g->nodes[p_id].node->disconnect_changed(callable_mp(this, &VisualShader::_queue_update));
859
860 g->nodes.erase(p_id);
861
862 for (List<Connection>::Element *E = g->connections.front(); E;) {
863 List<Connection>::Element *N = E->next();
864 if (E->get().from_node == p_id || E->get().to_node == p_id) {
865 g->connections.erase(E);
866 if (E->get().from_node == p_id) {
867 g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id);
868 g->nodes[E->get().to_node].node->set_input_port_connected(E->get().to_port, false);
869 } else if (E->get().to_node == p_id) {
870 g->nodes[E->get().from_node].next_connected_nodes.erase(p_id);
871 }
872 }
873 E = N;
874 }
875
876 _queue_update();
877}
878
879void VisualShader::replace_node(Type p_type, int p_id, const StringName &p_new_class) {
880 ERR_FAIL_INDEX(p_type, TYPE_MAX);
881 ERR_FAIL_COND(p_id < 2);
882 Graph *g = &graph[p_type];
883 ERR_FAIL_COND(!g->nodes.has(p_id));
884
885 if (g->nodes[p_id].node->get_class_name() == p_new_class) {
886 return;
887 }
888 VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instantiate(p_new_class));
889 VisualShaderNode *prev_vsn = g->nodes[p_id].node.ptr();
890
891 // Update connection data.
892 for (int i = 0; i < vsn->get_output_port_count(); i++) {
893 if (i < prev_vsn->get_output_port_count()) {
894 if (prev_vsn->is_output_port_connected(i)) {
895 vsn->set_output_port_connected(i, true);
896 }
897
898 if (prev_vsn->is_output_port_expandable(i) && prev_vsn->_is_output_port_expanded(i) && vsn->is_output_port_expandable(i)) {
899 vsn->_set_output_port_expanded(i, true);
900
901 int component_count = 0;
902 switch (prev_vsn->get_output_port_type(i)) {
903 case VisualShaderNode::PORT_TYPE_VECTOR_2D:
904 component_count = 2;
905 break;
906 case VisualShaderNode::PORT_TYPE_VECTOR_3D:
907 component_count = 3;
908 break;
909 case VisualShaderNode::PORT_TYPE_VECTOR_4D:
910 component_count = 4;
911 break;
912 default:
913 break;
914 }
915
916 for (int j = 0; j < component_count; j++) {
917 int sub_port = i + 1 + j;
918
919 if (prev_vsn->is_output_port_connected(sub_port)) {
920 vsn->set_output_port_connected(sub_port, true);
921 }
922 }
923
924 i += component_count;
925 }
926 } else {
927 break;
928 }
929 }
930
931 vsn->connect_changed(callable_mp(this, &VisualShader::_queue_update));
932 g->nodes[p_id].node = Ref<VisualShaderNode>(vsn);
933
934 _queue_update();
935}
936
937bool VisualShader::is_node_connection(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const {
938 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false);
939 const Graph *g = &graph[p_type];
940
941 for (const Connection &E : g->connections) {
942 if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
943 return true;
944 }
945 }
946
947 return false;
948}
949
950bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_node, int p_target) const {
951 bool result = false;
952
953 const VisualShader::Node &node = p_graph->nodes[p_node];
954
955 for (const int &E : node.prev_connected_nodes) {
956 if (E == p_target) {
957 return true;
958 }
959
960 result = is_nodes_connected_relatively(p_graph, E, p_target);
961 if (result) {
962 break;
963 }
964 }
965 return result;
966}
967
968bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) const {
969 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false);
970 const Graph *g = &graph[p_type];
971
972 if (!g->nodes.has(p_from_node)) {
973 return false;
974 }
975
976 if (p_from_node == p_to_node) {
977 return false;
978 }
979
980 if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_expanded_output_port_count()) {
981 return false;
982 }
983
984 if (!g->nodes.has(p_to_node)) {
985 return false;
986 }
987
988 if (p_to_port < 0 || p_to_port >= g->nodes[p_to_node].node->get_input_port_count()) {
989 return false;
990 }
991
992 VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
993 VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
994
995 if (!is_port_types_compatible(from_port_type, to_port_type)) {
996 return false;
997 }
998
999 for (const Connection &E : g->connections) {
1000 if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
1001 return false;
1002 }
1003 }
1004
1005 if (is_nodes_connected_relatively(g, p_from_node, p_to_node)) {
1006 return false;
1007 }
1008
1009 return true;
1010}
1011
1012bool VisualShader::is_port_types_compatible(int p_a, int p_b) const {
1013 return MAX(0, p_a - (int)VisualShaderNode::PORT_TYPE_BOOLEAN) == (MAX(0, p_b - (int)VisualShaderNode::PORT_TYPE_BOOLEAN));
1014}
1015
1016void VisualShader::connect_nodes_forced(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1017 ERR_FAIL_INDEX(p_type, TYPE_MAX);
1018 Graph *g = &graph[p_type];
1019
1020 ERR_FAIL_COND(!g->nodes.has(p_from_node));
1021 ERR_FAIL_INDEX(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count());
1022 ERR_FAIL_COND(!g->nodes.has(p_to_node));
1023 ERR_FAIL_INDEX(p_to_port, g->nodes[p_to_node].node->get_input_port_count());
1024
1025 for (const Connection &E : g->connections) {
1026 if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
1027 return;
1028 }
1029 }
1030
1031 Connection c;
1032 c.from_node = p_from_node;
1033 c.from_port = p_from_port;
1034 c.to_node = p_to_node;
1035 c.to_port = p_to_port;
1036 g->connections.push_back(c);
1037 g->nodes[p_from_node].next_connected_nodes.push_back(p_to_node);
1038 g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node);
1039 g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true);
1040 g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true);
1041
1042 _queue_update();
1043}
1044
1045Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1046 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, ERR_CANT_CONNECT);
1047 Graph *g = &graph[p_type];
1048
1049 ERR_FAIL_COND_V(!g->nodes.has(p_from_node), ERR_INVALID_PARAMETER);
1050 ERR_FAIL_INDEX_V(p_from_port, g->nodes[p_from_node].node->get_expanded_output_port_count(), ERR_INVALID_PARAMETER);
1051 ERR_FAIL_COND_V(!g->nodes.has(p_to_node), ERR_INVALID_PARAMETER);
1052 ERR_FAIL_INDEX_V(p_to_port, g->nodes[p_to_node].node->get_input_port_count(), ERR_INVALID_PARAMETER);
1053
1054 VisualShaderNode::PortType from_port_type = g->nodes[p_from_node].node->get_output_port_type(p_from_port);
1055 VisualShaderNode::PortType to_port_type = g->nodes[p_to_node].node->get_input_port_type(p_to_port);
1056
1057 ERR_FAIL_COND_V_MSG(!is_port_types_compatible(from_port_type, to_port_type), ERR_INVALID_PARAMETER, "Incompatible port types (scalar/vec/bool) with transform.");
1058
1059 for (const Connection &E : g->connections) {
1060 if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
1061 ERR_FAIL_V(ERR_ALREADY_EXISTS);
1062 }
1063 }
1064
1065 Connection c;
1066 c.from_node = p_from_node;
1067 c.from_port = p_from_port;
1068 c.to_node = p_to_node;
1069 c.to_port = p_to_port;
1070 g->connections.push_back(c);
1071 g->nodes[p_from_node].next_connected_nodes.push_back(p_to_node);
1072 g->nodes[p_to_node].prev_connected_nodes.push_back(p_from_node);
1073 g->nodes[p_from_node].node->set_output_port_connected(p_from_port, true);
1074 g->nodes[p_to_node].node->set_input_port_connected(p_to_port, true);
1075
1076 _queue_update();
1077 return OK;
1078}
1079
1080void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1081 ERR_FAIL_INDEX(p_type, TYPE_MAX);
1082 Graph *g = &graph[p_type];
1083
1084 for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
1085 if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
1086 g->connections.erase(E);
1087 g->nodes[p_from_node].next_connected_nodes.erase(p_to_node);
1088 g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node);
1089 g->nodes[p_from_node].node->set_output_port_connected(p_from_port, false);
1090 g->nodes[p_to_node].node->set_input_port_connected(p_to_port, false);
1091 _queue_update();
1092 return;
1093 }
1094 }
1095}
1096
1097TypedArray<Dictionary> VisualShader::_get_node_connections(Type p_type) const {
1098 ERR_FAIL_INDEX_V(p_type, TYPE_MAX, Array());
1099 const Graph *g = &graph[p_type];
1100
1101 TypedArray<Dictionary> ret;
1102 for (const Connection &E : g->connections) {
1103 Dictionary d;
1104 d["from_node"] = E.from_node;
1105 d["from_port"] = E.from_port;
1106 d["to_node"] = E.to_node;
1107 d["to_port"] = E.to_port;
1108 ret.push_back(d);
1109 }
1110
1111 return ret;
1112}
1113
1114void VisualShader::get_node_connections(Type p_type, List<Connection> *r_connections) const {
1115 ERR_FAIL_INDEX(p_type, TYPE_MAX);
1116 const Graph *g = &graph[p_type];
1117
1118 for (const Connection &E : g->connections) {
1119 r_connections->push_back(E);
1120 }
1121}
1122
1123void VisualShader::set_mode(Mode p_mode) {
1124 ERR_FAIL_INDEX_MSG(p_mode, Mode::MODE_MAX, vformat("Invalid shader mode: %d.", p_mode));
1125
1126 if (shader_mode == p_mode) {
1127 return;
1128 }
1129
1130 //erase input/output connections
1131 modes.clear();
1132 flags.clear();
1133 shader_mode = p_mode;
1134 for (int i = 0; i < TYPE_MAX; i++) {
1135 for (KeyValue<int, Node> &E : graph[i].nodes) {
1136 Ref<VisualShaderNodeInput> input = E.value.node;
1137 if (input.is_valid()) {
1138 input->shader_mode = shader_mode;
1139 //input->input_index = 0;
1140 }
1141 }
1142
1143 Ref<VisualShaderNodeOutput> output = graph[i].nodes[NODE_ID_OUTPUT].node;
1144 output->shader_mode = shader_mode;
1145
1146 // clear connections since they are no longer valid
1147 for (List<Connection>::Element *E = graph[i].connections.front(); E;) {
1148 bool keep = true;
1149
1150 List<Connection>::Element *N = E->next();
1151
1152 int from = E->get().from_node;
1153 int to = E->get().to_node;
1154
1155 if (!graph[i].nodes.has(from)) {
1156 keep = false;
1157 } else {
1158 Ref<VisualShaderNode> from_node = graph[i].nodes[from].node;
1159 if (from_node->is_class("VisualShaderNodeOutput") || from_node->is_class("VisualShaderNodeInput")) {
1160 keep = false;
1161 }
1162 }
1163
1164 if (!graph[i].nodes.has(to)) {
1165 keep = false;
1166 } else {
1167 Ref<VisualShaderNode> to_node = graph[i].nodes[to].node;
1168 if (to_node->is_class("VisualShaderNodeOutput") || to_node->is_class("VisualShaderNodeInput")) {
1169 keep = false;
1170 }
1171 }
1172
1173 if (!keep) {
1174 graph[i].connections.erase(E);
1175 }
1176 E = N;
1177 }
1178 }
1179
1180 _queue_update();
1181 notify_property_list_changed();
1182}
1183
1184void VisualShader::set_graph_offset(const Vector2 &p_offset) {
1185 graph_offset = p_offset;
1186}
1187
1188Vector2 VisualShader::get_graph_offset() const {
1189 return graph_offset;
1190}
1191
1192Shader::Mode VisualShader::get_mode() const {
1193 return shader_mode;
1194}
1195
1196bool VisualShader::is_text_shader() const {
1197 return false;
1198}
1199
1200String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port, Vector<DefaultTextureParam> &default_tex_params) const {
1201 Ref<VisualShaderNode> node = get_node(p_type, p_node);
1202 ERR_FAIL_COND_V(!node.is_valid(), String());
1203 ERR_FAIL_COND_V(p_port < 0 || p_port >= node->get_expanded_output_port_count(), String());
1204 ERR_FAIL_COND_V(node->get_output_port_type(p_port) == VisualShaderNode::PORT_TYPE_TRANSFORM, String());
1205
1206 StringBuilder global_code;
1207 StringBuilder global_code_per_node;
1208 HashMap<Type, StringBuilder> global_code_per_func;
1209 StringBuilder shader_code;
1210 HashSet<StringName> classes;
1211
1212 global_code += String() + "shader_type canvas_item;\n";
1213
1214 String global_expressions;
1215 for (int i = 0, index = 0; i < TYPE_MAX; i++) {
1216 for (const KeyValue<int, Node> &E : graph[i].nodes) {
1217 Ref<VisualShaderNodeGlobalExpression> global_expression = E.value.node;
1218 if (global_expression.is_valid()) {
1219 String expr = "";
1220 expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n";
1221 expr += global_expression->generate_global(get_mode(), Type(i), -1);
1222 expr = expr.replace("\n", "\n ");
1223 expr += "\n";
1224 global_expressions += expr;
1225 }
1226 }
1227 }
1228
1229 global_code += "\n";
1230 global_code += global_expressions;
1231
1232 //make it faster to go around through shader
1233 VMap<ConnectionKey, const List<Connection>::Element *> input_connections;
1234 VMap<ConnectionKey, const List<Connection>::Element *> output_connections;
1235
1236 for (const List<Connection>::Element *E = graph[p_type].connections.front(); E; E = E->next()) {
1237 ConnectionKey from_key;
1238 from_key.node = E->get().from_node;
1239 from_key.port = E->get().from_port;
1240
1241 output_connections.insert(from_key, E);
1242
1243 ConnectionKey to_key;
1244 to_key.node = E->get().to_node;
1245 to_key.port = E->get().to_port;
1246
1247 input_connections.insert(to_key, E);
1248 }
1249
1250 shader_code += "\nvoid fragment() {\n";
1251
1252 HashSet<int> processed;
1253 Error err = _write_node(p_type, &global_code, &global_code_per_node, &global_code_per_func, shader_code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
1254 ERR_FAIL_COND_V(err != OK, String());
1255
1256 switch (node->get_output_port_type(p_port)) {
1257 case VisualShaderNode::PORT_TYPE_SCALAR: {
1258 shader_code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ");\n";
1259 } break;
1260 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1261 shader_code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
1262 } break;
1263 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1264 shader_code += " COLOR.rgb = vec3(float(n_out" + itos(p_node) + "p" + itos(p_port) + "));\n";
1265 } break;
1266 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1267 shader_code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + " ? 1.0 : 0.0);\n";
1268 } break;
1269 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1270 shader_code += " COLOR.rgb = vec3(n_out" + itos(p_node) + "p" + itos(p_port) + ", 0.0);\n";
1271 } break;
1272 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1273 shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
1274 } break;
1275 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1276 shader_code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ".xyz;\n";
1277 } break;
1278 default: {
1279 shader_code += " COLOR.rgb = vec3(0.0);\n";
1280 } break;
1281 }
1282
1283 shader_code += "}\n";
1284
1285 //set code secretly
1286 global_code += "\n\n";
1287 String final_code = global_code;
1288 final_code += global_code_per_node;
1289 final_code += shader_code;
1290 return final_code;
1291}
1292
1293String VisualShader::validate_port_name(const String &p_port_name, VisualShaderNode *p_node, int p_port_id, bool p_output) const {
1294 String port_name = p_port_name;
1295
1296 if (port_name.is_empty()) {
1297 return String();
1298 }
1299
1300 while (port_name.length() && !is_ascii_char(port_name[0])) {
1301 port_name = port_name.substr(1, port_name.length() - 1);
1302 }
1303
1304 if (!port_name.is_empty()) {
1305 String valid_name;
1306
1307 for (int i = 0; i < port_name.length(); i++) {
1308 if (is_ascii_identifier_char(port_name[i])) {
1309 valid_name += String::chr(port_name[i]);
1310 } else if (port_name[i] == ' ') {
1311 valid_name += "_";
1312 }
1313 }
1314
1315 port_name = valid_name;
1316 } else {
1317 return String();
1318 }
1319
1320 List<String> input_names;
1321 List<String> output_names;
1322
1323 for (int i = 0; i < p_node->get_input_port_count(); i++) {
1324 if (!p_output && i == p_port_id) {
1325 continue;
1326 }
1327 if (port_name == p_node->get_input_port_name(i)) {
1328 return String();
1329 }
1330 }
1331 for (int i = 0; i < p_node->get_output_port_count(); i++) {
1332 if (p_output && i == p_port_id) {
1333 continue;
1334 }
1335 if (port_name == p_node->get_output_port_name(i)) {
1336 return String();
1337 }
1338 }
1339
1340 return port_name;
1341}
1342
1343String VisualShader::validate_parameter_name(const String &p_name, const Ref<VisualShaderNodeParameter> &p_parameter) const {
1344 String param_name = p_name; //validate name first
1345 while (param_name.length() && !is_ascii_char(param_name[0])) {
1346 param_name = param_name.substr(1, param_name.length() - 1);
1347 }
1348 if (!param_name.is_empty()) {
1349 String valid_name;
1350
1351 for (int i = 0; i < param_name.length(); i++) {
1352 if (is_ascii_identifier_char(param_name[i])) {
1353 valid_name += String::chr(param_name[i]);
1354 } else if (param_name[i] == ' ') {
1355 valid_name += "_";
1356 }
1357 }
1358
1359 param_name = valid_name;
1360 }
1361
1362 if (param_name.is_empty()) {
1363 param_name = p_parameter->get_caption();
1364 }
1365
1366 int attempt = 1;
1367
1368 while (true) {
1369 bool exists = false;
1370 for (int i = 0; i < TYPE_MAX; i++) {
1371 for (const KeyValue<int, Node> &E : graph[i].nodes) {
1372 Ref<VisualShaderNodeParameter> node = E.value.node;
1373 if (node == p_parameter) { //do not test on self
1374 continue;
1375 }
1376 if (node.is_valid() && node->get_parameter_name() == param_name) {
1377 exists = true;
1378 break;
1379 }
1380 }
1381 if (exists) {
1382 break;
1383 }
1384 }
1385
1386 if (exists) {
1387 //remove numbers, put new and try again
1388 attempt++;
1389 while (param_name.length() && is_digit(param_name[param_name.length() - 1])) {
1390 param_name = param_name.substr(0, param_name.length() - 1);
1391 }
1392 ERR_FAIL_COND_V(param_name.is_empty(), String());
1393 param_name += itos(attempt);
1394 } else {
1395 break;
1396 }
1397 }
1398
1399 return param_name;
1400}
1401
1402static const char *type_string[VisualShader::TYPE_MAX] = {
1403 "vertex",
1404 "fragment",
1405 "light",
1406 "start",
1407 "process",
1408 "collide",
1409 "start_custom",
1410 "process_custom",
1411 "sky",
1412 "fog",
1413};
1414
1415bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
1416 String prop_name = p_name;
1417 if (prop_name == "mode") {
1418 set_mode(Shader::Mode(int(p_value)));
1419 return true;
1420 } else if (prop_name.begins_with("flags/")) {
1421 StringName flag = prop_name.get_slicec('/', 1);
1422 bool enable = p_value;
1423 if (enable) {
1424 flags.insert(flag);
1425 } else {
1426 flags.erase(flag);
1427 }
1428 _queue_update();
1429 return true;
1430 } else if (prop_name.begins_with("modes/")) {
1431 String mode_name = prop_name.get_slicec('/', 1);
1432 int value = p_value;
1433 if (value == 0) {
1434 modes.erase(mode_name); //means it's default anyway, so don't store it
1435 } else {
1436 modes[mode_name] = value;
1437 }
1438 _queue_update();
1439 return true;
1440 } else if (prop_name.begins_with("varyings/")) {
1441 String var_name = prop_name.get_slicec('/', 1);
1442 Varying value = Varying();
1443 value.name = var_name;
1444 if (value.from_string(p_value) && !varyings.has(var_name)) {
1445 varyings[var_name] = value;
1446 varyings_list.push_back(value);
1447 }
1448 _queue_update();
1449 return true;
1450 } else if (prop_name.begins_with("nodes/")) {
1451 String typestr = prop_name.get_slicec('/', 1);
1452 Type type = TYPE_VERTEX;
1453 for (int i = 0; i < TYPE_MAX; i++) {
1454 if (typestr == type_string[i]) {
1455 type = Type(i);
1456 break;
1457 }
1458 }
1459
1460 String index = prop_name.get_slicec('/', 2);
1461 if (index == "connections") {
1462 Vector<int> conns = p_value;
1463 if (conns.size() % 4 == 0) {
1464 for (int i = 0; i < conns.size(); i += 4) {
1465 connect_nodes_forced(type, conns[i + 0], conns[i + 1], conns[i + 2], conns[i + 3]);
1466 }
1467 }
1468 return true;
1469 }
1470
1471 int id = index.to_int();
1472 String what = prop_name.get_slicec('/', 3);
1473
1474 if (what == "node") {
1475 add_node(type, p_value, Vector2(), id);
1476 return true;
1477 } else if (what == "position") {
1478 set_node_position(type, id, p_value);
1479 return true;
1480 } else if (what == "size") {
1481 ((VisualShaderNodeResizableBase *)get_node(type, id).ptr())->set_size(p_value);
1482 return true;
1483 } else if (what == "input_ports") {
1484 ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->set_inputs(p_value);
1485 return true;
1486 } else if (what == "output_ports") {
1487 ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->set_outputs(p_value);
1488 return true;
1489 } else if (what == "expression") {
1490 ((VisualShaderNodeExpression *)get_node(type, id).ptr())->set_expression(p_value);
1491 return true;
1492 }
1493 }
1494 return false;
1495}
1496
1497bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
1498 String prop_name = p_name;
1499 if (prop_name == "mode") {
1500 r_ret = get_mode();
1501 return true;
1502 } else if (prop_name.begins_with("flags/")) {
1503 StringName flag = prop_name.get_slicec('/', 1);
1504 r_ret = flags.has(flag);
1505 return true;
1506 } else if (prop_name.begins_with("modes/")) {
1507 String mode_name = prop_name.get_slicec('/', 1);
1508 if (modes.has(mode_name)) {
1509 r_ret = modes[mode_name];
1510 } else {
1511 r_ret = 0;
1512 }
1513 return true;
1514 } else if (prop_name.begins_with("varyings/")) {
1515 String var_name = prop_name.get_slicec('/', 1);
1516 if (varyings.has(var_name)) {
1517 r_ret = varyings[var_name].to_string();
1518 } else {
1519 r_ret = String();
1520 }
1521 return true;
1522 } else if (prop_name.begins_with("nodes/")) {
1523 String typestr = prop_name.get_slicec('/', 1);
1524 Type type = TYPE_VERTEX;
1525 for (int i = 0; i < TYPE_MAX; i++) {
1526 if (typestr == type_string[i]) {
1527 type = Type(i);
1528 break;
1529 }
1530 }
1531
1532 String index = prop_name.get_slicec('/', 2);
1533 if (index == "connections") {
1534 Vector<int> conns;
1535 for (const Connection &E : graph[type].connections) {
1536 conns.push_back(E.from_node);
1537 conns.push_back(E.from_port);
1538 conns.push_back(E.to_node);
1539 conns.push_back(E.to_port);
1540 }
1541
1542 r_ret = conns;
1543 return true;
1544 }
1545
1546 int id = index.to_int();
1547 String what = prop_name.get_slicec('/', 3);
1548
1549 if (what == "node") {
1550 r_ret = get_node(type, id);
1551 return true;
1552 } else if (what == "position") {
1553 r_ret = get_node_position(type, id);
1554 return true;
1555 } else if (what == "size") {
1556 r_ret = ((VisualShaderNodeResizableBase *)get_node(type, id).ptr())->get_size();
1557 return true;
1558 } else if (what == "input_ports") {
1559 r_ret = ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->get_inputs();
1560 return true;
1561 } else if (what == "output_ports") {
1562 r_ret = ((VisualShaderNodeGroupBase *)get_node(type, id).ptr())->get_outputs();
1563 return true;
1564 } else if (what == "expression") {
1565 r_ret = ((VisualShaderNodeExpression *)get_node(type, id).ptr())->get_expression();
1566 return true;
1567 }
1568 }
1569 return false;
1570}
1571
1572void VisualShader::reset_state() {
1573 // TODO: Everything needs to be cleared here.
1574 emit_changed();
1575}
1576
1577void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
1578 //mode
1579 p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Node3D,CanvasItem,Particles,Sky,Fog"));
1580 //render modes
1581
1582 HashMap<String, String> blend_mode_enums;
1583 HashSet<String> toggles;
1584
1585 const Vector<ShaderLanguage::ModeInfo> &rmodes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode));
1586
1587 for (int i = 0; i < rmodes.size(); i++) {
1588 const ShaderLanguage::ModeInfo &info = rmodes[i];
1589
1590 if (!info.options.is_empty()) {
1591 const String begin = String(info.name);
1592
1593 for (int j = 0; j < info.options.size(); j++) {
1594 const String option = String(info.options[j]).capitalize();
1595
1596 if (!blend_mode_enums.has(begin)) {
1597 blend_mode_enums[begin] = option;
1598 } else {
1599 blend_mode_enums[begin] += "," + option;
1600 }
1601 }
1602 } else {
1603 toggles.insert(String(info.name));
1604 }
1605 }
1606
1607 for (const KeyValue<String, String> &E : blend_mode_enums) {
1608 p_list->push_back(PropertyInfo(Variant::INT, vformat("%s/%s", PNAME("modes"), E.key), PROPERTY_HINT_ENUM, E.value));
1609 }
1610
1611 for (const String &E : toggles) {
1612 p_list->push_back(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("flags"), E)));
1613 }
1614
1615 for (const KeyValue<String, Varying> &E : varyings) {
1616 p_list->push_back(PropertyInfo(Variant::STRING, vformat("%s/%s", PNAME("varyings"), E.key)));
1617 }
1618
1619 for (int i = 0; i < TYPE_MAX; i++) {
1620 for (const KeyValue<int, Node> &E : graph[i].nodes) {
1621 String prop_name = "nodes/";
1622 prop_name += type_string[i];
1623 prop_name += "/" + itos(E.key);
1624
1625 if (E.key != NODE_ID_OUTPUT) {
1626 p_list->push_back(PropertyInfo(Variant::OBJECT, prop_name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_ALWAYS_DUPLICATE));
1627 }
1628 p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1629
1630 if (Object::cast_to<VisualShaderNodeGroupBase>(E.value.node.ptr()) != nullptr) {
1631 p_list->push_back(PropertyInfo(Variant::VECTOR2, prop_name + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1632 p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/input_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1633 p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1634 }
1635 if (Object::cast_to<VisualShaderNodeExpression>(E.value.node.ptr()) != nullptr) {
1636 p_list->push_back(PropertyInfo(Variant::STRING, prop_name + "/expression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1637 }
1638 }
1639 p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "nodes/" + String(type_string[i]) + "/connections", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR));
1640 }
1641}
1642
1643Error VisualShader::_write_node(Type type, StringBuilder *p_global_code, StringBuilder *p_global_code_per_node, HashMap<Type, StringBuilder> *p_global_code_per_func, StringBuilder &r_code, Vector<VisualShader::DefaultTextureParam> &r_def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &p_input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &p_output_connections, int p_node, HashSet<int> &r_processed, bool p_for_preview, HashSet<StringName> &r_classes) const {
1644 const Ref<VisualShaderNode> vsnode = graph[type].nodes[p_node].node;
1645
1646 if (vsnode->is_disabled()) {
1647 r_code += "// " + vsnode->get_caption() + ":" + itos(p_node) + "\n";
1648 r_code += " // Node is disabled and code is not generated.\n";
1649 return OK;
1650 }
1651
1652 //check inputs recursively first
1653 int input_count = vsnode->get_input_port_count();
1654 for (int i = 0; i < input_count; i++) {
1655 ConnectionKey ck;
1656 ck.node = p_node;
1657 ck.port = i;
1658
1659 if (p_input_connections.has(ck)) {
1660 int from_node = p_input_connections[ck]->get().from_node;
1661 if (r_processed.has(from_node)) {
1662 continue;
1663 }
1664
1665 Error err = _write_node(type, p_global_code, p_global_code_per_node, p_global_code_per_func, r_code, r_def_tex_params, p_input_connections, p_output_connections, from_node, r_processed, p_for_preview, r_classes);
1666 if (err) {
1667 return err;
1668 }
1669 }
1670 }
1671
1672 // then this node
1673
1674 Vector<VisualShader::DefaultTextureParam> params = vsnode->get_default_texture_parameters(type, p_node);
1675 for (int i = 0; i < params.size(); i++) {
1676 r_def_tex_params.push_back(params[i]);
1677 }
1678
1679 Ref<VisualShaderNodeInput> input = vsnode;
1680 bool skip_global = input.is_valid() && p_for_preview;
1681
1682 if (!skip_global) {
1683 Ref<VisualShaderNodeParameter> parameter = vsnode;
1684 if (!parameter.is_valid() || !parameter->is_global_code_generated()) {
1685 if (p_global_code) {
1686 *p_global_code += vsnode->generate_global(get_mode(), type, p_node);
1687 }
1688 }
1689
1690 String class_name = vsnode->get_class_name();
1691 if (class_name == "VisualShaderNodeCustom") {
1692 class_name = vsnode->get_script_instance()->get_script()->get_path();
1693 }
1694 if (!r_classes.has(class_name)) {
1695 if (p_global_code_per_node) {
1696 *p_global_code_per_node += vsnode->generate_global_per_node(get_mode(), p_node);
1697 }
1698 for (int i = 0; i < TYPE_MAX; i++) {
1699 if (p_global_code_per_func) {
1700 (*p_global_code_per_func)[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), p_node);
1701 }
1702 }
1703 r_classes.insert(class_name);
1704 }
1705 }
1706
1707 if (!vsnode->is_code_generated()) { // just generate globals and ignore locals
1708 r_processed.insert(p_node);
1709 return OK;
1710 }
1711
1712 String node_name = "// " + vsnode->get_caption() + ":" + itos(p_node) + "\n";
1713 String node_code;
1714 Vector<String> input_vars;
1715
1716 input_vars.resize(vsnode->get_input_port_count());
1717 String *inputs = input_vars.ptrw();
1718
1719 for (int i = 0; i < input_count; i++) {
1720 ConnectionKey ck;
1721 ck.node = p_node;
1722 ck.port = i;
1723
1724 if (p_input_connections.has(ck)) {
1725 //connected to something, use that output
1726 int from_node = p_input_connections[ck]->get().from_node;
1727
1728 if (graph[type].nodes[from_node].node->is_disabled()) {
1729 continue;
1730 }
1731
1732 int from_port = p_input_connections[ck]->get().from_port;
1733
1734 VisualShaderNode::PortType in_type = vsnode->get_input_port_type(i);
1735 VisualShaderNode::PortType out_type = graph[type].nodes[from_node].node->get_output_port_type(from_port);
1736
1737 String src_var = "n_out" + itos(from_node) + "p" + itos(from_port);
1738
1739 if (in_type == VisualShaderNode::PORT_TYPE_SAMPLER && out_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
1740 VisualShaderNode *ptr = const_cast<VisualShaderNode *>(graph[type].nodes[from_node].node.ptr());
1741 if (ptr->has_method("get_input_real_name")) {
1742 inputs[i] = ptr->call("get_input_real_name");
1743 } else if (ptr->has_method("get_parameter_name")) {
1744 inputs[i] = ptr->call("get_parameter_name");
1745 } else {
1746 inputs[i] = "";
1747 }
1748 } else if (in_type == out_type) {
1749 inputs[i] = src_var;
1750 } else {
1751 switch (in_type) {
1752 case VisualShaderNode::PORT_TYPE_SCALAR: {
1753 switch (out_type) {
1754 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1755 inputs[i] = "float(" + src_var + ")";
1756 } break;
1757 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1758 inputs[i] = "float(" + src_var + ")";
1759 } break;
1760 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1761 inputs[i] = "(" + src_var + " ? 1.0 : 0.0)";
1762 } break;
1763 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1764 inputs[i] = src_var + ".x";
1765 } break;
1766 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1767 inputs[i] = src_var + ".x";
1768 } break;
1769 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1770 inputs[i] = src_var + ".x";
1771 } break;
1772 default:
1773 break;
1774 }
1775 } break;
1776 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1777 switch (out_type) {
1778 case VisualShaderNode::PORT_TYPE_SCALAR: {
1779 inputs[i] = "int(" + src_var + ")";
1780 } break;
1781 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1782 inputs[i] = "int(" + src_var + ")";
1783 } break;
1784 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1785 inputs[i] = "(" + src_var + " ? 1 : 0)";
1786 } break;
1787 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1788 inputs[i] = "int(" + src_var + ".x)";
1789 } break;
1790 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1791 inputs[i] = "int(" + src_var + ".x)";
1792 } break;
1793 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1794 inputs[i] = "int(" + src_var + ".x)";
1795 } break;
1796 default:
1797 break;
1798 }
1799 } break;
1800 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1801 switch (out_type) {
1802 case VisualShaderNode::PORT_TYPE_SCALAR: {
1803 inputs[i] = "uint(" + src_var + ")";
1804 } break;
1805 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1806 inputs[i] = "uint(" + src_var + ")";
1807 } break;
1808 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1809 inputs[i] = "(" + src_var + " ? 1u : 0u)";
1810 } break;
1811 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1812 inputs[i] = "uint(" + src_var + ".x)";
1813 } break;
1814 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1815 inputs[i] = "uint(" + src_var + ".x)";
1816 } break;
1817 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1818 inputs[i] = "uint(" + src_var + ".x)";
1819 } break;
1820 default:
1821 break;
1822 }
1823 } break;
1824 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1825 switch (out_type) {
1826 case VisualShaderNode::PORT_TYPE_SCALAR: {
1827 inputs[i] = src_var + " > 0.0 ? true : false";
1828 } break;
1829 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1830 inputs[i] = src_var + " > 0 ? true : false";
1831 } break;
1832 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1833 inputs[i] = src_var + " > 0u ? true : false";
1834 } break;
1835 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1836 inputs[i] = "all(bvec2(" + src_var + "))";
1837 } break;
1838 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1839 inputs[i] = "all(bvec3(" + src_var + "))";
1840 } break;
1841 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1842 inputs[i] = "all(bvec4(" + src_var + "))";
1843 } break;
1844 default:
1845 break;
1846 }
1847 } break;
1848 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1849 switch (out_type) {
1850 case VisualShaderNode::PORT_TYPE_SCALAR: {
1851 inputs[i] = "vec2(" + src_var + ")";
1852 } break;
1853 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1854 inputs[i] = "vec2(float(" + src_var + "))";
1855 } break;
1856 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1857 inputs[i] = "vec2(float(" + src_var + "))";
1858 } break;
1859 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1860 inputs[i] = "vec2(" + src_var + " ? 1.0 : 0.0)";
1861 } break;
1862 case VisualShaderNode::PORT_TYPE_VECTOR_3D:
1863 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1864 inputs[i] = "vec2(" + src_var + ".xy)";
1865 } break;
1866 default:
1867 break;
1868 }
1869 } break;
1870
1871 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1872 switch (out_type) {
1873 case VisualShaderNode::PORT_TYPE_SCALAR: {
1874 inputs[i] = "vec3(" + src_var + ")";
1875 } break;
1876 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1877 inputs[i] = "vec3(float(" + src_var + "))";
1878 } break;
1879 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1880 inputs[i] = "vec3(float(" + src_var + "))";
1881 } break;
1882 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1883 inputs[i] = "vec3(" + src_var + " ? 1.0 : 0.0)";
1884 } break;
1885 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1886 inputs[i] = "vec3(" + src_var + ", 0.0)";
1887 } break;
1888 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1889 inputs[i] = "vec3(" + src_var + ".xyz)";
1890 } break;
1891 default:
1892 break;
1893 }
1894 } break;
1895 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1896 switch (out_type) {
1897 case VisualShaderNode::PORT_TYPE_SCALAR: {
1898 inputs[i] = "vec4(" + src_var + ")";
1899 } break;
1900 case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
1901 inputs[i] = "vec4(float(" + src_var + "))";
1902 } break;
1903 case VisualShaderNode::PORT_TYPE_SCALAR_UINT: {
1904 inputs[i] = "vec4(float(" + src_var + "))";
1905 } break;
1906 case VisualShaderNode::PORT_TYPE_BOOLEAN: {
1907 inputs[i] = "vec4(" + src_var + " ? 1.0 : 0.0)";
1908 } break;
1909 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1910 inputs[i] = "vec4(" + src_var + ", 0.0, 0.0)";
1911 } break;
1912 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1913 inputs[i] = "vec4(" + src_var + ", 0.0)";
1914 } break;
1915 default:
1916 break;
1917 }
1918 } break;
1919 default:
1920 break;
1921 }
1922 }
1923 } else {
1924 if (!vsnode->is_generate_input_var(i)) {
1925 continue;
1926 }
1927
1928 Variant defval = vsnode->get_input_port_default_value(i);
1929 if (defval.get_type() == Variant::FLOAT) {
1930 float val = defval;
1931 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1932 node_code += " float " + inputs[i] + " = " + vformat("%.5f", val) + ";\n";
1933 } else if (defval.get_type() == Variant::INT) {
1934 int val = defval;
1935 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1936 if (vsnode->get_input_port_type(i) == VisualShaderNode::PORT_TYPE_SCALAR_UINT) {
1937 node_code += " uint " + inputs[i] + " = " + itos(val) + "u;\n";
1938 } else {
1939 node_code += " int " + inputs[i] + " = " + itos(val) + ";\n";
1940 }
1941 } else if (defval.get_type() == Variant::BOOL) {
1942 bool val = defval;
1943 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1944 node_code += " bool " + inputs[i] + " = " + (val ? "true" : "false") + ";\n";
1945 } else if (defval.get_type() == Variant::VECTOR2) {
1946 Vector2 val = defval;
1947 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1948 node_code += " vec2 " + inputs[i] + " = " + vformat("vec2(%.5f, %.5f);\n", val.x, val.y);
1949 } else if (defval.get_type() == Variant::VECTOR3) {
1950 Vector3 val = defval;
1951 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1952 node_code += " vec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
1953 } else if (defval.get_type() == Variant::QUATERNION) {
1954 Quaternion val = defval;
1955 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1956 node_code += " vec4 " + inputs[i] + " = " + vformat("vec4(%.5f, %.5f, %.5f, %.5f);\n", val.x, val.y, val.z, val.w);
1957 } else if (defval.get_type() == Variant::TRANSFORM3D) {
1958 Transform3D val = defval;
1959 val.basis.transpose();
1960 inputs[i] = "n_in" + itos(p_node) + "p" + itos(i);
1961 Array values;
1962 for (int j = 0; j < 3; j++) {
1963 values.push_back(val.basis[j].x);
1964 values.push_back(val.basis[j].y);
1965 values.push_back(val.basis[j].z);
1966 }
1967 values.push_back(val.origin.x);
1968 values.push_back(val.origin.y);
1969 values.push_back(val.origin.z);
1970 bool err = false;
1971 node_code += " mat4 " + inputs[i] + " = " + String("mat4(vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 0.0), vec4(%.5f, %.5f, %.5f, 1.0));\n").sprintf(values, &err);
1972 } else {
1973 //will go empty, node is expected to know what it is doing at this point and handle it
1974 }
1975 }
1976 }
1977
1978 int output_count = vsnode->get_output_port_count();
1979 int initial_output_count = output_count;
1980
1981 HashMap<int, bool> expanded_output_ports;
1982
1983 for (int i = 0; i < initial_output_count; i++) {
1984 bool expanded = false;
1985
1986 if (vsnode->is_output_port_expandable(i) && vsnode->_is_output_port_expanded(i)) {
1987 expanded = true;
1988
1989 switch (vsnode->get_output_port_type(i)) {
1990 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1991 output_count += 2;
1992 } break;
1993 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1994 output_count += 3;
1995 } break;
1996 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1997 output_count += 4;
1998 } break;
1999 default:
2000 break;
2001 }
2002 }
2003 expanded_output_ports.insert(i, expanded);
2004 }
2005
2006 Vector<String> output_vars;
2007 output_vars.resize(output_count);
2008 String *outputs = output_vars.ptrw();
2009
2010 if (vsnode->is_simple_decl()) { // less code to generate for some simple_decl nodes
2011 for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
2012 String var_name = "n_out" + itos(p_node) + "p" + itos(j);
2013 switch (vsnode->get_output_port_type(i)) {
2014 case VisualShaderNode::PORT_TYPE_SCALAR:
2015 outputs[i] = "float " + var_name;
2016 break;
2017 case VisualShaderNode::PORT_TYPE_SCALAR_INT:
2018 outputs[i] = "int " + var_name;
2019 break;
2020 case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
2021 outputs[i] = "uint " + var_name;
2022 break;
2023 case VisualShaderNode::PORT_TYPE_VECTOR_2D:
2024 outputs[i] = "vec2 " + var_name;
2025 break;
2026 case VisualShaderNode::PORT_TYPE_VECTOR_3D:
2027 outputs[i] = "vec3 " + var_name;
2028 break;
2029 case VisualShaderNode::PORT_TYPE_VECTOR_4D:
2030 outputs[i] = "vec4 " + var_name;
2031 break;
2032 case VisualShaderNode::PORT_TYPE_BOOLEAN:
2033 outputs[i] = "bool " + var_name;
2034 break;
2035 case VisualShaderNode::PORT_TYPE_TRANSFORM:
2036 outputs[i] = "mat4 " + var_name;
2037 break;
2038 default:
2039 break;
2040 }
2041 if (expanded_output_ports[i]) {
2042 switch (vsnode->get_output_port_type(i)) {
2043 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
2044 j += 2;
2045 } break;
2046 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
2047 j += 3;
2048 } break;
2049 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
2050 j += 4;
2051 } break;
2052 default:
2053 break;
2054 }
2055 }
2056 }
2057
2058 } else {
2059 for (int i = 0, j = 0; i < initial_output_count; i++, j++) {
2060 outputs[i] = "n_out" + itos(p_node) + "p" + itos(j);
2061 switch (vsnode->get_output_port_type(i)) {
2062 case VisualShaderNode::PORT_TYPE_SCALAR:
2063 r_code += " float " + outputs[i] + ";\n";
2064 break;
2065 case VisualShaderNode::PORT_TYPE_SCALAR_INT:
2066 r_code += " int " + outputs[i] + ";\n";
2067 break;
2068 case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
2069 r_code += " uint " + outputs[i] + ";\n";
2070 break;
2071 case VisualShaderNode::PORT_TYPE_VECTOR_2D:
2072 r_code += " vec2 " + outputs[i] + ";\n";
2073 break;
2074 case VisualShaderNode::PORT_TYPE_VECTOR_3D:
2075 r_code += " vec3 " + outputs[i] + ";\n";
2076 break;
2077 case VisualShaderNode::PORT_TYPE_VECTOR_4D:
2078 r_code += " vec4 " + outputs[i] + ";\n";
2079 break;
2080 case VisualShaderNode::PORT_TYPE_BOOLEAN:
2081 r_code += " bool " + outputs[i] + ";\n";
2082 break;
2083 case VisualShaderNode::PORT_TYPE_TRANSFORM:
2084 r_code += " mat4 " + outputs[i] + ";\n";
2085 break;
2086 default:
2087 break;
2088 }
2089 if (expanded_output_ports[i]) {
2090 switch (vsnode->get_output_port_type(i)) {
2091 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
2092 j += 2;
2093 } break;
2094 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
2095 j += 3;
2096 } break;
2097 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
2098 j += 4;
2099 } break;
2100 default:
2101 break;
2102 }
2103 }
2104 }
2105 }
2106
2107 node_code += vsnode->generate_code(get_mode(), type, p_node, inputs, outputs, p_for_preview);
2108 if (!node_code.is_empty()) {
2109 r_code += node_name;
2110 r_code += node_code;
2111 }
2112
2113 for (int i = 0; i < output_count; i++) {
2114 if (expanded_output_ports[i]) {
2115 switch (vsnode->get_output_port_type(i)) {
2116 case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
2117 if (vsnode->is_output_port_connected(i + 1) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
2118 String r = "n_out" + itos(p_node) + "p" + itos(i + 1);
2119 r_code += " float " + r + " = n_out" + itos(p_node) + "p" + itos(i) + ".r;\n";
2120 outputs[i + 1] = r;
2121 }
2122
2123 if (vsnode->is_output_port_connected(i + 2) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
2124 String g = "n_out" + itos(p_node) + "p" + itos(i + 2);
2125 r_code += " float " + g + " = n_out" + itos(p_node) + "p" + itos(i) + ".g;\n";
2126 outputs[i + 2] = g;
2127 }
2128
2129 i += 2;
2130 } break;
2131 case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
2132 if (vsnode->is_output_port_connected(i + 1) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
2133 String r = "n_out" + itos(p_node) + "p" + itos(i + 1);
2134 r_code += " float " + r + " = n_out" + itos(p_node) + "p" + itos(i) + ".r;\n";
2135 outputs[i + 1] = r;
2136 }
2137
2138 if (vsnode->is_output_port_connected(i + 2) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
2139 String g = "n_out" + itos(p_node) + "p" + itos(i + 2);
2140 r_code += " float " + g + " = n_out" + itos(p_node) + "p" + itos(i) + ".g;\n";
2141 outputs[i + 2] = g;
2142 }
2143
2144 if (vsnode->is_output_port_connected(i + 3) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
2145 String b = "n_out" + itos(p_node) + "p" + itos(i + 3);
2146 r_code += " float " + b + " = n_out" + itos(p_node) + "p" + itos(i) + ".b;\n";
2147 outputs[i + 3] = b;
2148 }
2149
2150 i += 3;
2151 } break;
2152 case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
2153 if (vsnode->is_output_port_connected(i + 1) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
2154 String r = "n_out" + itos(p_node) + "p" + itos(i + 1);
2155 r_code += " float " + r + " = n_out" + itos(p_node) + "p" + itos(i) + ".r;\n";
2156 outputs[i + 1] = r;
2157 }
2158
2159 if (vsnode->is_output_port_connected(i + 2) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
2160 String g = "n_out" + itos(p_node) + "p" + itos(i + 2);
2161 r_code += " float " + g + " = n_out" + itos(p_node) + "p" + itos(i) + ".g;\n";
2162 outputs[i + 2] = g;
2163 }
2164
2165 if (vsnode->is_output_port_connected(i + 3) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
2166 String b = "n_out" + itos(p_node) + "p" + itos(i + 3);
2167 r_code += " float " + b + " = n_out" + itos(p_node) + "p" + itos(i) + ".b;\n";
2168 outputs[i + 3] = b;
2169 }
2170
2171 if (vsnode->is_output_port_connected(i + 4) || (p_for_preview && vsnode->get_output_port_for_preview() == (i + 4))) { // alpha-component
2172 String a = "n_out" + itos(p_node) + "p" + itos(i + 4);
2173 r_code += " float " + a + " = n_out" + itos(p_node) + "p" + itos(i) + ".a;\n";
2174 outputs[i + 4] = a;
2175 }
2176
2177 i += 4;
2178 } break;
2179 default:
2180 break;
2181 }
2182 }
2183 }
2184
2185 if (!node_code.is_empty()) {
2186 r_code += "\n\n";
2187 }
2188
2189 r_processed.insert(p_node);
2190
2191 return OK;
2192}
2193
2194bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const {
2195 if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) {
2196 if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) {
2197 if (p_func_name == "start_custom" || p_func_name == "process_custom" || p_func_name == "collide") {
2198 return true;
2199 }
2200 }
2201 return false;
2202 }
2203
2204 return true;
2205}
2206
2207void VisualShader::_update_shader() const {
2208 if (!dirty.is_set()) {
2209 return;
2210 }
2211
2212 dirty.clear();
2213
2214 StringBuilder global_code;
2215 StringBuilder global_code_per_node;
2216 HashMap<Type, StringBuilder> global_code_per_func;
2217 StringBuilder shader_code;
2218 Vector<VisualShader::DefaultTextureParam> default_tex_params;
2219 HashSet<StringName> classes;
2220 HashMap<int, int> insertion_pos;
2221 static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles", "sky", "fog" };
2222
2223 global_code += String() + "shader_type " + shader_mode_str[shader_mode] + ";\n";
2224
2225 String render_mode;
2226
2227 {
2228 const Vector<ShaderLanguage::ModeInfo> &rmodes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode));
2229 Vector<String> flag_names;
2230
2231 // Add enum modes first.
2232 for (int i = 0; i < rmodes.size(); i++) {
2233 const ShaderLanguage::ModeInfo &info = rmodes[i];
2234 const String temp = String(info.name);
2235
2236 if (!info.options.is_empty()) {
2237 if (!render_mode.is_empty()) {
2238 render_mode += ", ";
2239 }
2240 // Always write out a render_mode for the enumerated modes as having no render mode is not always
2241 // the same as the default. i.e. for depth_draw_opaque, the render mode has to be declared for it
2242 // to work properly, no render mode is an invalid option.
2243 if (modes.has(temp) && modes[temp] < info.options.size()) {
2244 render_mode += temp + "_" + info.options[modes[temp]];
2245 } else {
2246 // Use the default.
2247 render_mode += temp + "_" + info.options[0];
2248 }
2249 } else if (flags.has(temp)) {
2250 flag_names.push_back(temp);
2251 }
2252 }
2253
2254 // Add flags afterward.
2255 for (int i = 0; i < flag_names.size(); i++) {
2256 if (!render_mode.is_empty()) {
2257 render_mode += ", ";
2258 }
2259 render_mode += flag_names[i];
2260 }
2261 }
2262
2263 if (!render_mode.is_empty()) {
2264 global_code += "render_mode " + render_mode + ";\n\n";
2265 }
2266
2267 static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
2268
2269 String global_expressions;
2270 HashSet<String> used_parameter_names;
2271 List<VisualShaderNodeParameter *> parameters;
2272 HashMap<int, List<int>> emitters;
2273 HashMap<int, List<int>> varying_setters;
2274
2275 for (int i = 0, index = 0; i < TYPE_MAX; i++) {
2276 if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
2277 continue;
2278 }
2279
2280 for (const KeyValue<int, Node> &E : graph[i].nodes) {
2281 Ref<VisualShaderNodeGlobalExpression> global_expression = E.value.node;
2282 if (global_expression.is_valid()) {
2283 String expr = "";
2284 expr += "// " + global_expression->get_caption() + ":" + itos(index++) + "\n";
2285 expr += global_expression->generate_global(get_mode(), Type(i), -1);
2286 expr = expr.replace("\n", "\n ");
2287 expr += "\n";
2288 global_expressions += expr;
2289 }
2290 Ref<VisualShaderNodeParameterRef> parameter_ref = E.value.node;
2291 if (parameter_ref.is_valid()) {
2292 used_parameter_names.insert(parameter_ref->get_parameter_name());
2293 }
2294 Ref<VisualShaderNodeParameter> parameter = E.value.node;
2295 if (parameter.is_valid()) {
2296 parameters.push_back(parameter.ptr());
2297 }
2298 Ref<VisualShaderNodeVaryingSetter> varying_setter = E.value.node;
2299 if (varying_setter.is_valid() && varying_setter->is_input_port_connected(0)) {
2300 if (!varying_setters.has(i)) {
2301 varying_setters.insert(i, List<int>());
2302 }
2303 varying_setters[i].push_back(E.key);
2304 }
2305 Ref<VisualShaderNodeParticleEmit> emit_particle = E.value.node;
2306 if (emit_particle.is_valid()) {
2307 if (!emitters.has(i)) {
2308 emitters.insert(i, List<int>());
2309 }
2310 emitters[i].push_back(E.key);
2311 }
2312 }
2313 }
2314
2315 for (int i = 0; i < parameters.size(); i++) {
2316 VisualShaderNodeParameter *parameter = parameters[i];
2317 if (used_parameter_names.has(parameter->get_parameter_name())) {
2318 global_code += parameter->generate_global(get_mode(), Type(i), -1);
2319 const_cast<VisualShaderNodeParameter *>(parameter)->set_global_code_generated(true);
2320 } else {
2321 const_cast<VisualShaderNodeParameter *>(parameter)->set_global_code_generated(false);
2322 }
2323 }
2324
2325 if (!varyings.is_empty()) {
2326 global_code += "\n// Varyings\n";
2327
2328 for (const KeyValue<String, Varying> &E : varyings) {
2329 global_code += "varying ";
2330 switch (E.value.type) {
2331 case VaryingType::VARYING_TYPE_FLOAT:
2332 global_code += "float ";
2333 break;
2334 case VaryingType::VARYING_TYPE_INT:
2335 if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) {
2336 global_code += "flat ";
2337 }
2338 global_code += "int ";
2339 break;
2340 case VaryingType::VARYING_TYPE_UINT:
2341 if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) {
2342 global_code += "flat ";
2343 }
2344 global_code += "uint ";
2345 break;
2346 case VaryingType::VARYING_TYPE_VECTOR_2D:
2347 global_code += "vec2 ";
2348 break;
2349 case VaryingType::VARYING_TYPE_VECTOR_3D:
2350 global_code += "vec3 ";
2351 break;
2352 case VaryingType::VARYING_TYPE_VECTOR_4D:
2353 global_code += "vec4 ";
2354 break;
2355 case VaryingType::VARYING_TYPE_BOOLEAN:
2356 if (E.value.mode == VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) {
2357 global_code += "flat ";
2358 }
2359 global_code += "bool ";
2360 break;
2361 case VaryingType::VARYING_TYPE_TRANSFORM:
2362 global_code += "mat4 ";
2363 break;
2364 default:
2365 break;
2366 }
2367 global_code += E.key + ";\n";
2368 }
2369
2370 global_code += "\n";
2371 }
2372
2373 HashMap<int, String> code_map;
2374 HashSet<int> empty_funcs;
2375
2376 for (int i = 0; i < TYPE_MAX; i++) {
2377 if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
2378 continue;
2379 }
2380
2381 //make it faster to go around through shader
2382 VMap<ConnectionKey, const List<Connection>::Element *> input_connections;
2383 VMap<ConnectionKey, const List<Connection>::Element *> output_connections;
2384
2385 StringBuilder func_code;
2386 HashSet<int> processed;
2387
2388 bool is_empty_func = false;
2389 if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG) {
2390 is_empty_func = true;
2391 }
2392
2393 String varying_code;
2394 if (shader_mode == Shader::MODE_SPATIAL || shader_mode == Shader::MODE_CANVAS_ITEM) {
2395 for (const KeyValue<String, Varying> &E : varyings) {
2396 if ((E.value.mode == VARYING_MODE_VERTEX_TO_FRAG_LIGHT && i == TYPE_VERTEX) || (E.value.mode == VARYING_MODE_FRAG_TO_LIGHT && i == TYPE_FRAGMENT)) {
2397 bool found = false;
2398 for (int key : varying_setters[i]) {
2399 Ref<VisualShaderNodeVaryingSetter> setter = Object::cast_to<VisualShaderNodeVaryingSetter>(const_cast<VisualShaderNode *>(graph[i].nodes[key].node.ptr()));
2400 if (setter.is_valid() && E.value.name == setter->get_varying_name()) {
2401 found = true;
2402 break;
2403 }
2404 }
2405
2406 if (!found) {
2407 String code2;
2408 switch (E.value.type) {
2409 case VaryingType::VARYING_TYPE_FLOAT:
2410 code2 += "0.0";
2411 break;
2412 case VaryingType::VARYING_TYPE_INT:
2413 code2 += "0";
2414 break;
2415 case VaryingType::VARYING_TYPE_UINT:
2416 code2 += "0u";
2417 break;
2418 case VaryingType::VARYING_TYPE_VECTOR_2D:
2419 code2 += "vec2(0.0)";
2420 break;
2421 case VaryingType::VARYING_TYPE_VECTOR_3D:
2422 code2 += "vec3(0.0)";
2423 break;
2424 case VaryingType::VARYING_TYPE_VECTOR_4D:
2425 code2 += "vec4(0.0)";
2426 break;
2427 case VaryingType::VARYING_TYPE_BOOLEAN:
2428 code2 += "false";
2429 break;
2430 case VaryingType::VARYING_TYPE_TRANSFORM:
2431 code2 += "mat4(1.0)";
2432 break;
2433 default:
2434 break;
2435 }
2436 varying_code += vformat(" %s = %s;\n", E.key, code2);
2437 }
2438 is_empty_func = false;
2439 }
2440 }
2441 }
2442
2443 for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) {
2444 ConnectionKey from_key;
2445 from_key.node = E->get().from_node;
2446 from_key.port = E->get().from_port;
2447
2448 output_connections.insert(from_key, E);
2449
2450 ConnectionKey to_key;
2451 to_key.node = E->get().to_node;
2452 to_key.port = E->get().to_port;
2453
2454 input_connections.insert(to_key, E);
2455
2456 if (is_empty_func && to_key.node == NODE_ID_OUTPUT) {
2457 is_empty_func = false;
2458 }
2459 }
2460
2461 if (is_empty_func) {
2462 empty_funcs.insert(i);
2463 continue;
2464 }
2465
2466 if (shader_mode != Shader::MODE_PARTICLES) {
2467 func_code += "\nvoid " + String(func_name[i]) + "() {\n";
2468 }
2469 insertion_pos.insert(i, shader_code.get_string_length() + func_code.get_string_length());
2470
2471 Error err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
2472 ERR_FAIL_COND(err != OK);
2473
2474 if (varying_setters.has(i)) {
2475 for (int &E : varying_setters[i]) {
2476 err = _write_node(Type(i), nullptr, nullptr, nullptr, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
2477 ERR_FAIL_COND(err != OK);
2478 }
2479 }
2480
2481 if (emitters.has(i)) {
2482 for (int &E : emitters[i]) {
2483 err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
2484 ERR_FAIL_COND(err != OK);
2485 }
2486 }
2487
2488 if (shader_mode == Shader::MODE_PARTICLES) {
2489 code_map.insert(i, func_code);
2490 } else {
2491 func_code += varying_code;
2492 func_code += "}\n";
2493 shader_code += func_code;
2494 }
2495 }
2496
2497 String global_compute_code;
2498
2499 if (shader_mode == Shader::MODE_PARTICLES) {
2500 bool has_start_custom = !code_map[TYPE_START_CUSTOM].is_empty();
2501 bool has_process = !code_map[TYPE_PROCESS].is_empty();
2502 bool has_process_custom = !code_map[TYPE_PROCESS_CUSTOM].is_empty();
2503 bool has_collide = !code_map[TYPE_COLLIDE].is_empty();
2504
2505 shader_code += "void start() {\n";
2506 shader_code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
2507 shader_code += "\n";
2508 shader_code += " {\n";
2509 shader_code += code_map[TYPE_START].replace("\n ", "\n ");
2510 shader_code += " }\n";
2511 if (has_start_custom) {
2512 shader_code += " \n";
2513 shader_code += " {\n";
2514 shader_code += code_map[TYPE_START_CUSTOM].replace("\n ", "\n ");
2515 shader_code += " }\n";
2516 }
2517 shader_code += "}\n\n";
2518
2519 if (has_process || has_process_custom || has_collide) {
2520 shader_code += "void process() {\n";
2521 shader_code += " uint __seed = __hash(NUMBER + uint(1) + RANDOM_SEED);\n";
2522 shader_code += "\n";
2523 if (has_process || has_collide) {
2524 shader_code += " {\n";
2525 }
2526 String tab = " ";
2527 if (has_collide) {
2528 shader_code += " if (COLLIDED) {\n\n";
2529 shader_code += code_map[TYPE_COLLIDE].replace("\n ", "\n ");
2530 if (has_process) {
2531 shader_code += " } else {\n\n";
2532 tab += " ";
2533 }
2534 }
2535 if (has_process) {
2536 shader_code += code_map[TYPE_PROCESS].replace("\n ", "\n " + tab);
2537 }
2538 if (has_collide) {
2539 shader_code += " }\n";
2540 }
2541 if (has_process || has_collide) {
2542 shader_code += " }\n";
2543 }
2544
2545 if (has_process_custom) {
2546 if (has_process || has_collide) {
2547 shader_code += " \n";
2548 }
2549 shader_code += " {\n";
2550 shader_code += code_map[TYPE_PROCESS_CUSTOM].replace("\n ", "\n ");
2551 shader_code += " }\n";
2552 }
2553
2554 shader_code += "}\n\n";
2555 }
2556
2557 global_compute_code += "float __rand_from_seed(inout uint seed) {\n";
2558 global_compute_code += " int k;\n";
2559 global_compute_code += " int s = int(seed);\n";
2560 global_compute_code += " if (s == 0)\n";
2561 global_compute_code += " s = 305420679;\n";
2562 global_compute_code += " k = s / 127773;\n";
2563 global_compute_code += " s = 16807 * (s - k * 127773) - 2836 * k;\n";
2564 global_compute_code += " if (s < 0)\n";
2565 global_compute_code += " s += 2147483647;\n";
2566 global_compute_code += " seed = uint(s);\n";
2567 global_compute_code += " return float(seed % uint(65536)) / 65535.0;\n";
2568 global_compute_code += "}\n\n";
2569
2570 global_compute_code += "float __rand_from_seed_m1_p1(inout uint seed) {\n";
2571 global_compute_code += " return __rand_from_seed(seed) * 2.0 - 1.0;\n";
2572 global_compute_code += "}\n\n";
2573
2574 global_compute_code += "float __randf_range(inout uint seed, float from, float to) {\n";
2575 global_compute_code += " return __rand_from_seed(seed) * (to - from) + from;\n";
2576 global_compute_code += "}\n\n";
2577
2578 global_compute_code += "uint __hash(uint x) {\n";
2579 global_compute_code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
2580 global_compute_code += " x = ((x >> uint(16)) ^ x) * uint(73244475);\n";
2581 global_compute_code += " x = (x >> uint(16)) ^ x;\n";
2582 global_compute_code += " return x;\n";
2583 global_compute_code += "}\n\n";
2584
2585 global_compute_code += "mat3 __build_rotation_mat3(vec3 axis, float angle) {\n";
2586 global_compute_code += " axis = normalize(axis);\n";
2587 global_compute_code += " float s = sin(angle);\n";
2588 global_compute_code += " float c = cos(angle);\n";
2589 global_compute_code += " float oc = 1.0 - c;\n";
2590 global_compute_code += " return mat3(vec3(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s), vec3(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s), vec3(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c));\n";
2591 global_compute_code += "}\n\n";
2592
2593 global_compute_code += "mat4 __build_rotation_mat4(vec3 axis, float angle) {\n";
2594 global_compute_code += " axis = normalize(axis);\n";
2595 global_compute_code += " float s = sin(angle);\n";
2596 global_compute_code += " float c = cos(angle);\n";
2597 global_compute_code += " float oc = 1.0 - c;\n";
2598 global_compute_code += " return mat4(vec4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0), vec4(oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0), vec4(oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0), vec4(0, 0, 0, 1));\n";
2599 global_compute_code += "}\n\n";
2600
2601 global_compute_code += "vec2 __get_random_unit_vec2(inout uint seed) {\n";
2602 global_compute_code += " return normalize(vec2(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
2603 global_compute_code += "}\n\n";
2604
2605 global_compute_code += "vec3 __get_random_unit_vec3(inout uint seed) {\n";
2606 global_compute_code += " return normalize(vec3(__rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed), __rand_from_seed_m1_p1(seed)));\n";
2607 global_compute_code += "}\n\n";
2608 }
2609
2610 //set code secretly
2611 global_code += "\n\n";
2612 String final_code = global_code;
2613 final_code += global_compute_code;
2614 final_code += global_code_per_node;
2615 final_code += global_expressions;
2616 String tcode = shader_code;
2617 for (int i = 0; i < TYPE_MAX; i++) {
2618 if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
2619 continue;
2620 }
2621 String func_code = global_code_per_func[Type(i)].as_string();
2622 if (empty_funcs.has(Type(i)) && !func_code.is_empty()) {
2623 func_code = vformat("%s%s%s", String("\nvoid " + String(func_name[i]) + "() {\n"), func_code, "}\n");
2624 }
2625 tcode = tcode.insert(insertion_pos[i], func_code);
2626 }
2627 final_code += tcode;
2628
2629 const_cast<VisualShader *>(this)->set_code(final_code);
2630 for (int i = 0; i < default_tex_params.size(); i++) {
2631 for (int j = 0; j < default_tex_params[i].params.size(); j++) {
2632 const_cast<VisualShader *>(this)->set_default_texture_parameter(default_tex_params[i].name, default_tex_params[i].params[j], j);
2633 }
2634 }
2635 if (previous_code != final_code) {
2636 const_cast<VisualShader *>(this)->emit_signal(SNAME("changed"));
2637 }
2638 previous_code = final_code;
2639}
2640
2641void VisualShader::_queue_update() {
2642 if (dirty.is_set()) {
2643 return;
2644 }
2645
2646 dirty.set();
2647 call_deferred(SNAME("_update_shader"));
2648}
2649
2650void VisualShader::rebuild() {
2651 dirty.set();
2652 _update_shader();
2653}
2654
2655void VisualShader::_bind_methods() {
2656 ClassDB::bind_method(D_METHOD("set_mode", "mode"), &VisualShader::set_mode);
2657
2658 ClassDB::bind_method(D_METHOD("add_node", "type", "node", "position", "id"), &VisualShader::add_node);
2659 ClassDB::bind_method(D_METHOD("get_node", "type", "id"), &VisualShader::get_node);
2660
2661 ClassDB::bind_method(D_METHOD("set_node_position", "type", "id", "position"), &VisualShader::set_node_position);
2662 ClassDB::bind_method(D_METHOD("get_node_position", "type", "id"), &VisualShader::get_node_position);
2663
2664 ClassDB::bind_method(D_METHOD("get_node_list", "type"), &VisualShader::get_node_list);
2665 ClassDB::bind_method(D_METHOD("get_valid_node_id", "type"), &VisualShader::get_valid_node_id);
2666
2667 ClassDB::bind_method(D_METHOD("remove_node", "type", "id"), &VisualShader::remove_node);
2668 ClassDB::bind_method(D_METHOD("replace_node", "type", "id", "new_class"), &VisualShader::replace_node);
2669
2670 ClassDB::bind_method(D_METHOD("is_node_connection", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::is_node_connection);
2671 ClassDB::bind_method(D_METHOD("can_connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::can_connect_nodes);
2672
2673 ClassDB::bind_method(D_METHOD("connect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::connect_nodes);
2674 ClassDB::bind_method(D_METHOD("disconnect_nodes", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::disconnect_nodes);
2675 ClassDB::bind_method(D_METHOD("connect_nodes_forced", "type", "from_node", "from_port", "to_node", "to_port"), &VisualShader::connect_nodes_forced);
2676
2677 ClassDB::bind_method(D_METHOD("get_node_connections", "type"), &VisualShader::_get_node_connections);
2678
2679 ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &VisualShader::set_graph_offset);
2680 ClassDB::bind_method(D_METHOD("get_graph_offset"), &VisualShader::get_graph_offset);
2681
2682 ClassDB::bind_method(D_METHOD("add_varying", "name", "mode", "type"), &VisualShader::add_varying);
2683 ClassDB::bind_method(D_METHOD("remove_varying", "name"), &VisualShader::remove_varying);
2684 ClassDB::bind_method(D_METHOD("has_varying", "name"), &VisualShader::has_varying);
2685
2686 ClassDB::bind_method(D_METHOD("_update_shader"), &VisualShader::_update_shader);
2687
2688 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset");
2689
2690 ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs.
2691
2692 BIND_ENUM_CONSTANT(TYPE_VERTEX);
2693 BIND_ENUM_CONSTANT(TYPE_FRAGMENT);
2694 BIND_ENUM_CONSTANT(TYPE_LIGHT);
2695 BIND_ENUM_CONSTANT(TYPE_START);
2696 BIND_ENUM_CONSTANT(TYPE_PROCESS);
2697 BIND_ENUM_CONSTANT(TYPE_COLLIDE);
2698 BIND_ENUM_CONSTANT(TYPE_START_CUSTOM);
2699 BIND_ENUM_CONSTANT(TYPE_PROCESS_CUSTOM);
2700 BIND_ENUM_CONSTANT(TYPE_SKY);
2701 BIND_ENUM_CONSTANT(TYPE_FOG);
2702 BIND_ENUM_CONSTANT(TYPE_MAX);
2703
2704 BIND_ENUM_CONSTANT(VARYING_MODE_VERTEX_TO_FRAG_LIGHT);
2705 BIND_ENUM_CONSTANT(VARYING_MODE_FRAG_TO_LIGHT);
2706 BIND_ENUM_CONSTANT(VARYING_MODE_MAX);
2707
2708 BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT);
2709 BIND_ENUM_CONSTANT(VARYING_TYPE_INT);
2710 BIND_ENUM_CONSTANT(VARYING_TYPE_UINT);
2711 BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D);
2712 BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D);
2713 BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_4D);
2714 BIND_ENUM_CONSTANT(VARYING_TYPE_BOOLEAN);
2715 BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM);
2716 BIND_ENUM_CONSTANT(VARYING_TYPE_MAX);
2717
2718 BIND_CONSTANT(NODE_ID_INVALID);
2719 BIND_CONSTANT(NODE_ID_OUTPUT);
2720}
2721
2722VisualShader::VisualShader() {
2723 dirty.set();
2724 for (int i = 0; i < TYPE_MAX; i++) {
2725 if (i > (int)TYPE_LIGHT && i < (int)TYPE_SKY) {
2726 Ref<VisualShaderNodeParticleOutput> output;
2727 output.instantiate();
2728 output->shader_type = Type(i);
2729 output->shader_mode = shader_mode;
2730 graph[i].nodes[NODE_ID_OUTPUT].node = output;
2731 } else {
2732 Ref<VisualShaderNodeOutput> output;
2733 output.instantiate();
2734 output->shader_type = Type(i);
2735 output->shader_mode = shader_mode;
2736 graph[i].nodes[NODE_ID_OUTPUT].node = output;
2737 }
2738
2739 graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150);
2740 }
2741}
2742
2743///////////////////////////////////////////////////////////
2744
2745const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
2746 // Node3D
2747
2748 // Node3D, Vertex
2749 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" },
2750 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
2751 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
2752 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" },
2753 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
2754 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2755 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
2756 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2757 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
2758 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
2759 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" },
2760 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
2761 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
2762 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "modelview_matrix", "MODELVIEW_MATRIX" },
2763 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_view_matrix", "INV_VIEW_MATRIX" },
2764 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "view_matrix", "VIEW_MATRIX" },
2765 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection_matrix", "PROJECTION_MATRIX" },
2766 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection_matrix", "INV_PROJECTION_MATRIX" },
2767 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2768 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "exposure", "EXPOSURE" },
2769 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
2770 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
2771 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
2772 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
2773 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
2774 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eye_offset", "EYE_OFFSET" },
2775 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" },
2776 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" },
2777 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" },
2778 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" },
2779 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
2780 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom0", "CUSTOM0" },
2781 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom1", "CUSTOM1" },
2782 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom2", "CUSTOM2" },
2783 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom3", "CUSTOM3" },
2784
2785 // Node3D, Fragment
2786 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
2787 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" },
2788 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
2789 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" },
2790 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
2791 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "view", "VIEW" },
2792 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2793 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
2794 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2795 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
2796 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
2797 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
2798 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "view_matrix", "VIEW_MATRIX" },
2799 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_view_matrix", "INV_VIEW_MATRIX" },
2800 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection_matrix", "PROJECTION_MATRIX" },
2801 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection_matrix", "INV_PROJECTION_MATRIX" },
2802 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2803 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "exposure", "EXPOSURE" },
2804 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
2805 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
2806 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "front_facing", "FRONT_FACING" },
2807 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
2808 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
2809 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
2810 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eye_offset", "EYE_OFFSET" },
2811 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_world", "NODE_POSITION_WORLD" },
2812 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_position_world", "CAMERA_POSITION_WORLD" },
2813 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" },
2814 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" },
2815 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" },
2816
2817 // Node3D, Light
2818 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
2819 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
2820 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2821 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
2822 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "view", "VIEW" },
2823 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT" },
2824 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR" },
2825 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light_is_directional", "LIGHT_IS_DIRECTIONAL" },
2826 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "attenuation", "ATTENUATION" },
2827 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" },
2828 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" },
2829 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "diffuse", "DIFFUSE_LIGHT" },
2830 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular", "SPECULAR_LIGHT" },
2831 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
2832 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "metallic", "METALLIC" },
2833 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
2834 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "view_matrix", "VIEW_MATRIX" },
2835 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_view_matrix", "INV_VIEW_MATRIX" },
2836 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "projection_matrix", "PROJECTION_MATRIX" },
2837 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_TRANSFORM, "inv_projection_matrix", "INV_PROJECTION_MATRIX" },
2838 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2839 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "exposure", "EXPOSURE" },
2840 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
2841 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
2842
2843 // Canvas Item
2844
2845 // Canvas Item, Vertex
2846 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
2847 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2848 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2849 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
2850 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
2851 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
2852 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "canvas_matrix", "CANVAS_MATRIX" },
2853 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen_matrix", "SCREEN_MATRIX" },
2854 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2855 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
2856 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" },
2857 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
2858 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
2859
2860 // Canvas Item, Fragment
2861 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
2862 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2863 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2864 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
2865 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
2866 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_pixel_size", "SCREEN_PIXEL_SIZE" },
2867 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
2868 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2869 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
2870 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
2871 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_texture", "NORMAL_TEXTURE" },
2872 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" },
2873 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" },
2874 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
2875
2876 // Canvas Item, Light
2877 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
2878 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
2879 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
2880 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2881 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" },
2882 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light_color", "LIGHT_COLOR" },
2883 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_position", "LIGHT_POSITION" },
2884 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_direction", "LIGHT_DIRECTION" },
2885 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_BOOLEAN, "light_is_directional", "LIGHT_IS_DIRECTIONAL" },
2886 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_energy", "LIGHT_ENERGY" },
2887 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_vertex", "LIGHT_VERTEX" },
2888 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "shadow", "SHADOW_MODULATE" },
2889 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
2890 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
2891 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
2892 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2893 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
2894 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" },
2895
2896 // Particles, Start
2897 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
2898 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2899 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
2900 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
2901 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
2902 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
2903 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
2904 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
2905 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
2906 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "index", "INDEX" },
2907 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "number", "NUMBER" },
2908 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "random_seed", "RANDOM_SEED" },
2909 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
2910 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2911
2912 // Particles, Start (Custom)
2913 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
2914 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2915 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
2916 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
2917 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
2918 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
2919 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
2920 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
2921 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
2922 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "index", "INDEX" },
2923 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "number", "NUMBER" },
2924 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "random_seed", "RANDOM_SEED" },
2925 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
2926 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2927
2928 // Particles, Process
2929 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
2930 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2931 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
2932 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
2933 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
2934 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
2935 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
2936 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
2937 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
2938 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "index", "INDEX" },
2939 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "number", "NUMBER" },
2940 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "random_seed", "RANDOM_SEED" },
2941 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
2942 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2943
2944 // Particles, Process (Custom)
2945 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
2946 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2947 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
2948 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
2949 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
2950 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
2951 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
2952 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
2953 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
2954 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "index", "INDEX" },
2955 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "number", "NUMBER" },
2956 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "random_seed", "RANDOM_SEED" },
2957 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
2958 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2959
2960 // Particles, Collide
2961 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
2962 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "collision_depth", "COLLISION_DEPTH" },
2963 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "collision_normal", "COLLISION_NORMAL" },
2964 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
2965 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
2966 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
2967 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
2968 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
2969 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
2970 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
2971 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
2972 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "index", "INDEX" },
2973 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "number", "NUMBER" },
2974 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR_UINT, "random_seed", "RANDOM_SEED" },
2975 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" },
2976 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
2977
2978 // Sky, Sky
2979 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" },
2980 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_half_res_pass", "AT_HALF_RES_PASS" },
2981 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_quarter_res_pass", "AT_QUARTER_RES_PASS" },
2982 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eyedir", "EYEDIR" },
2983 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "half_res_color", "HALF_RES_COLOR" },
2984 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_color", "LIGHT0_COLOR" },
2985 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_direction", "LIGHT0_DIRECTION" },
2986 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light0_enabled", "LIGHT0_ENABLED" },
2987 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light0_energy", "LIGHT0_ENERGY" },
2988 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light1_color", "LIGHT1_COLOR" },
2989 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light1_direction", "LIGHT1_DIRECTION" },
2990 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light1_enabled", "LIGHT1_ENABLED" },
2991 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light1_energy", "LIGHT1_ENERGY" },
2992 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light2_color", "LIGHT2_COLOR" },
2993 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light2_direction", "LIGHT2_DIRECTION" },
2994 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light2_enabled", "LIGHT2_ENABLED" },
2995 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light2_energy", "LIGHT2_ENERGY" },
2996 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light3_color", "LIGHT3_COLOR" },
2997 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light3_direction", "LIGHT3_DIRECTION" },
2998 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light3_enabled", "LIGHT3_ENABLED" },
2999 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light3_energy", "LIGHT3_ENERGY" },
3000 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "position", "POSITION" },
3001 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "quarter_res_color", "QUARTER_RES_COLOR" },
3002 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" },
3003 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
3004 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
3005 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "sky_coords", "SKY_COORDS" },
3006 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3007
3008 // Fog, Fog
3009
3010 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "world_position", "WORLD_POSITION" },
3011 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "object_position", "OBJECT_POSITION" },
3012 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "uvw", "UVW" },
3013 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "size", "SIZE" },
3014 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "sdf", "SDF" },
3015 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3016
3017 { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
3018};
3019
3020const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
3021 // Spatial, Vertex
3022
3023 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
3024 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "vec3(0.0, 1.0, 0.0)" },
3025 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 0.0)" },
3026 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3027 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
3028 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
3029 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
3030 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
3031 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3032
3033 // Spatial, Fragment
3034
3035 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
3036 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
3037 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "vec3(0.0, 1.0, 0.0)" },
3038 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 0.0)" },
3039 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3040 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
3041 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
3042 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
3043 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
3044 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
3045 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3046
3047 // Spatial, Light
3048
3049 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
3050 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
3051 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3052 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
3053 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
3054 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3055
3056 // Canvas Item, Vertex
3057
3058 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
3059 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3060 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
3061 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
3062 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3063
3064 // Canvas Item, Fragment
3065
3066 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
3067 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3068 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec3(1.0)" },
3069 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
3070 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
3071 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3072
3073 // Canvas Item, Light
3074
3075 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
3076 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
3077 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
3078 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
3079 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
3080 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
3081 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3082
3083 // Particles
3084
3085 { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3086 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3087 { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3088 { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3089 { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3090
3091 // Sky
3092
3093 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
3094 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3095
3096 // Fog
3097
3098 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
3099
3100 { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
3101};
3102
3103int VisualShaderNodeInput::get_input_port_count() const {
3104 return 0;
3105}
3106
3107VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_port_type(int p_port) const {
3108 return PORT_TYPE_SCALAR;
3109}
3110
3111String VisualShaderNodeInput::get_input_port_name(int p_port) const {
3112 return "";
3113}
3114
3115int VisualShaderNodeInput::get_output_port_count() const {
3116 return 1;
3117}
3118
3119VisualShaderNodeInput::PortType VisualShaderNodeInput::get_output_port_type(int p_port) const {
3120 return p_port == 0 ? get_input_type_by_name(input_name) : PORT_TYPE_SCALAR;
3121}
3122
3123String VisualShaderNodeInput::get_output_port_name(int p_port) const {
3124 return "";
3125}
3126
3127String VisualShaderNodeInput::get_caption() const {
3128 return "Input";
3129}
3130
3131bool VisualShaderNodeInput::is_output_port_expandable(int p_port) const {
3132 if (p_port == 0) {
3133 switch (get_input_type_by_name(input_name)) {
3134 case PORT_TYPE_VECTOR_2D:
3135 return true;
3136 case PORT_TYPE_VECTOR_3D:
3137 return true;
3138 case PORT_TYPE_VECTOR_4D:
3139 return true;
3140 default:
3141 return false;
3142 }
3143 }
3144 return false;
3145}
3146
3147String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
3148 if (get_output_port_type(0) == PORT_TYPE_SAMPLER) {
3149 return "";
3150 }
3151
3152 if (p_for_preview) {
3153 int idx = 0;
3154
3155 String code;
3156
3157 while (preview_ports[idx].mode != Shader::MODE_MAX) {
3158 if (preview_ports[idx].mode == shader_mode && preview_ports[idx].shader_type == shader_type && preview_ports[idx].name == input_name) {
3159 code = " " + p_output_vars[0] + " = " + preview_ports[idx].string + ";\n";
3160 break;
3161 }
3162 idx++;
3163 }
3164
3165 if (code.is_empty()) {
3166 switch (get_output_port_type(0)) {
3167 case PORT_TYPE_SCALAR: {
3168 code = " " + p_output_vars[0] + " = 0.0;\n";
3169 } break;
3170 case PORT_TYPE_SCALAR_INT: {
3171 code = " " + p_output_vars[0] + " = 0;\n";
3172 } break;
3173 case PORT_TYPE_VECTOR_2D: {
3174 code = " " + p_output_vars[0] + " = vec2(0.0);\n";
3175 } break;
3176 case PORT_TYPE_VECTOR_3D: {
3177 code = " " + p_output_vars[0] + " = vec3(0.0);\n";
3178 } break;
3179 case PORT_TYPE_VECTOR_4D: {
3180 code = " " + p_output_vars[0] + " = vec4(0.0);\n";
3181 } break;
3182 case PORT_TYPE_BOOLEAN: {
3183 code = " " + p_output_vars[0] + " = false;\n";
3184 } break;
3185 default:
3186 break;
3187 }
3188 }
3189
3190 return code;
3191
3192 } else {
3193 int idx = 0;
3194
3195 String code;
3196
3197 while (ports[idx].mode != Shader::MODE_MAX) {
3198 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type && ports[idx].name == input_name) {
3199 code = " " + p_output_vars[0] + " = " + ports[idx].string + ";\n";
3200 break;
3201 }
3202 idx++;
3203 }
3204
3205 if (code.is_empty()) {
3206 code = " " + p_output_vars[0] + " = 0.0;\n"; //default (none found) is scalar
3207 }
3208
3209 return code;
3210 }
3211}
3212
3213void VisualShaderNodeInput::set_input_name(String p_name) {
3214 PortType prev_type = get_input_type_by_name(input_name);
3215 input_name = p_name;
3216 emit_changed();
3217 if (get_input_type_by_name(input_name) != prev_type) {
3218 emit_signal(SNAME("input_type_changed"));
3219 }
3220}
3221
3222String VisualShaderNodeInput::get_input_name() const {
3223 return input_name;
3224}
3225
3226String VisualShaderNodeInput::get_input_real_name() const {
3227 int idx = 0;
3228
3229 while (ports[idx].mode != Shader::MODE_MAX) {
3230 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type && ports[idx].name == input_name) {
3231 return String(ports[idx].string);
3232 }
3233 idx++;
3234 }
3235
3236 return "";
3237}
3238
3239VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_type_by_name(String p_name) const {
3240 int idx = 0;
3241
3242 while (ports[idx].mode != Shader::MODE_MAX) {
3243 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type && ports[idx].name == p_name) {
3244 return ports[idx].type;
3245 }
3246 idx++;
3247 }
3248
3249 return PORT_TYPE_SCALAR;
3250}
3251
3252int VisualShaderNodeInput::get_input_index_count() const {
3253 int idx = 0;
3254 int count = 0;
3255
3256 while (ports[idx].mode != Shader::MODE_MAX) {
3257 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3258 count++;
3259 }
3260 idx++;
3261 }
3262
3263 return count;
3264}
3265
3266VisualShaderNodeInput::PortType VisualShaderNodeInput::get_input_index_type(int p_index) const {
3267 int idx = 0;
3268 int count = 0;
3269
3270 while (ports[idx].mode != Shader::MODE_MAX) {
3271 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3272 if (count == p_index) {
3273 return ports[idx].type;
3274 }
3275 count++;
3276 }
3277 idx++;
3278 }
3279
3280 return PORT_TYPE_SCALAR;
3281}
3282
3283String VisualShaderNodeInput::get_input_index_name(int p_index) const {
3284 int idx = 0;
3285 int count = 0;
3286
3287 while (ports[idx].mode != Shader::MODE_MAX) {
3288 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3289 if (count == p_index) {
3290 return ports[idx].name;
3291 }
3292 count++;
3293 }
3294 idx++;
3295 }
3296
3297 return "";
3298}
3299
3300void VisualShaderNodeInput::_validate_property(PropertyInfo &p_property) const {
3301 if (p_property.name == "input_name") {
3302 String port_list;
3303
3304 int idx = 0;
3305
3306 while (ports[idx].mode != Shader::MODE_MAX) {
3307 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3308 if (!port_list.is_empty()) {
3309 port_list += ",";
3310 }
3311 port_list += ports[idx].name;
3312 }
3313 idx++;
3314 }
3315
3316 if (port_list.is_empty()) {
3317 port_list = RTR("None");
3318 }
3319 p_property.hint_string = port_list;
3320 }
3321}
3322
3323Vector<StringName> VisualShaderNodeInput::get_editable_properties() const {
3324 Vector<StringName> props;
3325 props.push_back("input_name");
3326 return props;
3327}
3328
3329void VisualShaderNodeInput::set_shader_type(VisualShader::Type p_shader_type) {
3330 shader_type = p_shader_type;
3331}
3332
3333void VisualShaderNodeInput::set_shader_mode(Shader::Mode p_shader_mode) {
3334 shader_mode = p_shader_mode;
3335}
3336
3337void VisualShaderNodeInput::_bind_methods() {
3338 ClassDB::bind_method(D_METHOD("set_input_name", "name"), &VisualShaderNodeInput::set_input_name);
3339 ClassDB::bind_method(D_METHOD("get_input_name"), &VisualShaderNodeInput::get_input_name);
3340 ClassDB::bind_method(D_METHOD("get_input_real_name"), &VisualShaderNodeInput::get_input_real_name);
3341
3342 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "input_name", PROPERTY_HINT_ENUM, ""), "set_input_name", "get_input_name");
3343 ADD_SIGNAL(MethodInfo("input_type_changed"));
3344}
3345
3346VisualShaderNodeInput::VisualShaderNodeInput() {
3347}
3348
3349////////////// ParameterRef
3350
3351RBMap<RID, List<VisualShaderNodeParameterRef::Parameter>> parameters;
3352
3353void VisualShaderNodeParameterRef::add_parameter(RID p_shader_rid, const String &p_name, ParameterType p_type) {
3354 parameters[p_shader_rid].push_back({ p_name, p_type });
3355}
3356
3357void VisualShaderNodeParameterRef::clear_parameters(RID p_shader_rid) {
3358 parameters[p_shader_rid].clear();
3359}
3360
3361bool VisualShaderNodeParameterRef::has_parameter(RID p_shader_rid, const String &p_name) {
3362 for (const VisualShaderNodeParameterRef::Parameter &E : parameters[p_shader_rid]) {
3363 if (E.name == p_name) {
3364 return true;
3365 }
3366 }
3367 return false;
3368}
3369
3370String VisualShaderNodeParameterRef::get_caption() const {
3371 return "ParameterRef";
3372}
3373
3374int VisualShaderNodeParameterRef::get_input_port_count() const {
3375 return 0;
3376}
3377
3378VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_input_port_type(int p_port) const {
3379 return PortType::PORT_TYPE_SCALAR;
3380}
3381
3382String VisualShaderNodeParameterRef::get_input_port_name(int p_port) const {
3383 return "";
3384}
3385
3386int VisualShaderNodeParameterRef::get_output_port_count() const {
3387 switch (param_type) {
3388 case PARAMETER_TYPE_FLOAT:
3389 return 1;
3390 case PARAMETER_TYPE_INT:
3391 return 1;
3392 case PARAMETER_TYPE_UINT:
3393 return 1;
3394 case PARAMETER_TYPE_BOOLEAN:
3395 return 1;
3396 case PARAMETER_TYPE_VECTOR2:
3397 return 1;
3398 case PARAMETER_TYPE_VECTOR3:
3399 return 1;
3400 case PARAMETER_TYPE_VECTOR4:
3401 return 1;
3402 case PARAMETER_TYPE_TRANSFORM:
3403 return 1;
3404 case PARAMETER_TYPE_COLOR:
3405 return 2;
3406 case UNIFORM_TYPE_SAMPLER:
3407 return 1;
3408 default:
3409 break;
3410 }
3411 return 1;
3412}
3413
3414VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_output_port_type(int p_port) const {
3415 switch (param_type) {
3416 case PARAMETER_TYPE_FLOAT:
3417 return PortType::PORT_TYPE_SCALAR;
3418 case PARAMETER_TYPE_INT:
3419 return PortType::PORT_TYPE_SCALAR_INT;
3420 case PARAMETER_TYPE_UINT:
3421 return PortType::PORT_TYPE_SCALAR_UINT;
3422 case PARAMETER_TYPE_BOOLEAN:
3423 return PortType::PORT_TYPE_BOOLEAN;
3424 case PARAMETER_TYPE_VECTOR2:
3425 return PortType::PORT_TYPE_VECTOR_2D;
3426 case PARAMETER_TYPE_VECTOR3:
3427 return PortType::PORT_TYPE_VECTOR_3D;
3428 case PARAMETER_TYPE_VECTOR4:
3429 return PortType::PORT_TYPE_VECTOR_4D;
3430 case PARAMETER_TYPE_TRANSFORM:
3431 return PortType::PORT_TYPE_TRANSFORM;
3432 case PARAMETER_TYPE_COLOR:
3433 if (p_port == 0) {
3434 return PortType::PORT_TYPE_VECTOR_3D;
3435 } else if (p_port == 1) {
3436 return PORT_TYPE_SCALAR;
3437 }
3438 break;
3439 case UNIFORM_TYPE_SAMPLER:
3440 return PortType::PORT_TYPE_SAMPLER;
3441 default:
3442 break;
3443 }
3444 return PORT_TYPE_SCALAR;
3445}
3446
3447String VisualShaderNodeParameterRef::get_output_port_name(int p_port) const {
3448 switch (param_type) {
3449 case PARAMETER_TYPE_FLOAT:
3450 return "";
3451 case PARAMETER_TYPE_INT:
3452 return "";
3453 case PARAMETER_TYPE_UINT:
3454 return "";
3455 case PARAMETER_TYPE_BOOLEAN:
3456 return "";
3457 case PARAMETER_TYPE_VECTOR2:
3458 return "";
3459 case PARAMETER_TYPE_VECTOR3:
3460 return "";
3461 case PARAMETER_TYPE_VECTOR4:
3462 return "";
3463 case PARAMETER_TYPE_TRANSFORM:
3464 return "";
3465 case PARAMETER_TYPE_COLOR:
3466 if (p_port == 0) {
3467 return "rgb";
3468 } else if (p_port == 1) {
3469 return "alpha";
3470 }
3471 break;
3472 case UNIFORM_TYPE_SAMPLER:
3473 return "";
3474 break;
3475 default:
3476 break;
3477 }
3478 return "";
3479}
3480
3481void VisualShaderNodeParameterRef::set_shader_rid(const RID &p_shader_rid) {
3482 shader_rid = p_shader_rid;
3483}
3484
3485void VisualShaderNodeParameterRef::set_parameter_name(const String &p_name) {
3486 parameter_name = p_name;
3487 if (shader_rid.is_valid()) {
3488 update_parameter_type();
3489 }
3490 emit_changed();
3491}
3492
3493void VisualShaderNodeParameterRef::update_parameter_type() {
3494 if (parameter_name != "[None]") {
3495 param_type = get_parameter_type_by_name(parameter_name);
3496 } else {
3497 param_type = PARAMETER_TYPE_FLOAT;
3498 }
3499}
3500
3501String VisualShaderNodeParameterRef::get_parameter_name() const {
3502 return parameter_name;
3503}
3504
3505int VisualShaderNodeParameterRef::get_parameters_count() const {
3506 ERR_FAIL_COND_V(!shader_rid.is_valid(), 0);
3507
3508 return parameters[shader_rid].size();
3509}
3510
3511String VisualShaderNodeParameterRef::get_parameter_name_by_index(int p_idx) const {
3512 ERR_FAIL_COND_V(!shader_rid.is_valid(), String());
3513
3514 if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
3515 return parameters[shader_rid][p_idx].name;
3516 }
3517 return "";
3518}
3519
3520VisualShaderNodeParameterRef::ParameterType VisualShaderNodeParameterRef::get_parameter_type_by_name(const String &p_name) const {
3521 ERR_FAIL_COND_V(!shader_rid.is_valid(), PARAMETER_TYPE_FLOAT);
3522
3523 for (int i = 0; i < parameters[shader_rid].size(); i++) {
3524 if (parameters[shader_rid][i].name == p_name) {
3525 return parameters[shader_rid][i].type;
3526 }
3527 }
3528 return PARAMETER_TYPE_FLOAT;
3529}
3530
3531VisualShaderNodeParameterRef::ParameterType VisualShaderNodeParameterRef::get_parameter_type_by_index(int p_idx) const {
3532 ERR_FAIL_COND_V(!shader_rid.is_valid(), PARAMETER_TYPE_FLOAT);
3533
3534 if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
3535 return parameters[shader_rid][p_idx].type;
3536 }
3537 return PARAMETER_TYPE_FLOAT;
3538}
3539
3540VisualShaderNodeParameterRef::PortType VisualShaderNodeParameterRef::get_port_type_by_index(int p_idx) const {
3541 ERR_FAIL_COND_V(!shader_rid.is_valid(), PORT_TYPE_SCALAR);
3542
3543 if (p_idx >= 0 && p_idx < parameters[shader_rid].size()) {
3544 switch (parameters[shader_rid][p_idx].type) {
3545 case PARAMETER_TYPE_FLOAT:
3546 return PORT_TYPE_SCALAR;
3547 case PARAMETER_TYPE_INT:
3548 return PORT_TYPE_SCALAR_INT;
3549 case PARAMETER_TYPE_UINT:
3550 return PORT_TYPE_SCALAR_UINT;
3551 case UNIFORM_TYPE_SAMPLER:
3552 return PORT_TYPE_SAMPLER;
3553 case PARAMETER_TYPE_VECTOR2:
3554 return PORT_TYPE_VECTOR_2D;
3555 case PARAMETER_TYPE_VECTOR3:
3556 return PORT_TYPE_VECTOR_3D;
3557 case PARAMETER_TYPE_VECTOR4:
3558 return PORT_TYPE_VECTOR_4D;
3559 case PARAMETER_TYPE_TRANSFORM:
3560 return PORT_TYPE_TRANSFORM;
3561 case PARAMETER_TYPE_COLOR:
3562 return PORT_TYPE_VECTOR_3D;
3563 default:
3564 break;
3565 }
3566 }
3567 return PORT_TYPE_SCALAR;
3568}
3569
3570String VisualShaderNodeParameterRef::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
3571 switch (param_type) {
3572 case PARAMETER_TYPE_FLOAT:
3573 if (parameter_name == "[None]") {
3574 return " " + p_output_vars[0] + " = 0.0;\n";
3575 }
3576 break;
3577 case PARAMETER_TYPE_COLOR: {
3578 String code = " " + p_output_vars[0] + " = " + get_parameter_name() + ".rgb;\n";
3579 code += " " + p_output_vars[1] + " = " + get_parameter_name() + ".a;\n";
3580 return code;
3581 } break;
3582 case UNIFORM_TYPE_SAMPLER:
3583 return String();
3584 default:
3585 break;
3586 }
3587
3588 return " " + p_output_vars[0] + " = " + get_parameter_name() + ";\n";
3589}
3590
3591void VisualShaderNodeParameterRef::_set_parameter_type(int p_type) {
3592 param_type = (ParameterType)p_type;
3593}
3594
3595int VisualShaderNodeParameterRef::_get_parameter_type() const {
3596 return (int)param_type;
3597}
3598
3599void VisualShaderNodeParameterRef::_bind_methods() {
3600 ClassDB::bind_method(D_METHOD("set_parameter_name", "name"), &VisualShaderNodeParameterRef::set_parameter_name);
3601 ClassDB::bind_method(D_METHOD("get_parameter_name"), &VisualShaderNodeParameterRef::get_parameter_name);
3602
3603 ClassDB::bind_method(D_METHOD("_set_parameter_type", "type"), &VisualShaderNodeParameterRef::_set_parameter_type);
3604 ClassDB::bind_method(D_METHOD("_get_parameter_type"), &VisualShaderNodeParameterRef::_get_parameter_type);
3605
3606 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "parameter_name", PROPERTY_HINT_ENUM, ""), "set_parameter_name", "get_parameter_name");
3607 ADD_PROPERTY(PropertyInfo(Variant::INT, "param_type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_parameter_type", "_get_parameter_type");
3608}
3609
3610Vector<StringName> VisualShaderNodeParameterRef::get_editable_properties() const {
3611 Vector<StringName> props;
3612 props.push_back("parameter_name");
3613 props.push_back("param_type");
3614 return props;
3615}
3616
3617VisualShaderNodeParameterRef::VisualShaderNodeParameterRef() {
3618}
3619
3620////////////////////////////////////////////
3621
3622const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
3623 ////////////////////////////////////////////////////////////////////////
3624 // Node3D.
3625 ////////////////////////////////////////////////////////////////////////
3626 // Node3D, Vertex.
3627 ////////////////////////////////////////////////////////////////////////
3628 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Vertex", "VERTEX" },
3629 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" },
3630 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Tangent", "TANGENT" },
3631 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Binormal", "BINORMAL" },
3632 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" },
3633 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV2", "UV2" },
3634 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
3635 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
3636 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Roughness", "ROUGHNESS" },
3637 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" },
3638 { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "Model View Matrix", "MODELVIEW_MATRIX" },
3639 ////////////////////////////////////////////////////////////////////////
3640 // Node3D, Fragment.
3641 ////////////////////////////////////////////////////////////////////////
3642 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" },
3643 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" },
3644 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Metallic", "METALLIC" },
3645 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Roughness", "ROUGHNESS" },
3646 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Specular", "SPECULAR" },
3647 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Emission", "EMISSION" },
3648 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "AO", "AO" },
3649 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "AO Light Affect", "AO_LIGHT_AFFECT" },
3650
3651 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" },
3652 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" },
3653 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" },
3654
3655 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim", "RIM" },
3656 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Rim Tint", "RIM_TINT" },
3657 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Clearcoat", "CLEARCOAT" },
3658 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Clearcoat Roughness", "CLEARCOAT_ROUGHNESS" },
3659 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Anisotropy", "ANISOTROPY" },
3660 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Anisotropy Flow", "ANISOTROPY_FLOW" },
3661 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Subsurf Scatter", "SSS_STRENGTH" },
3662 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Backlight", "BACKLIGHT" },
3663
3664 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha Scissor Threshold", "ALPHA_SCISSOR_THRESHOLD" },
3665 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha Hash Scale", "ALPHA_HASH_SCALE" },
3666 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha AA Edge", "ALPHA_ANTIALIASING_EDGE" },
3667 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Alpha UV", "ALPHA_TEXTURE_COORDINATE" },
3668
3669 { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Depth", "DEPTH" },
3670
3671 ////////////////////////////////////////////////////////////////////////
3672 // Node3D, Light.
3673 ////////////////////////////////////////////////////////////////////////
3674 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Diffuse", "DIFFUSE_LIGHT" },
3675 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Specular", "SPECULAR_LIGHT" },
3676 { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" },
3677
3678 ////////////////////////////////////////////////////////////////////////
3679 // Canvas Item.
3680 ////////////////////////////////////////////////////////////////////////
3681 // Canvas Item, Vertex.
3682 ////////////////////////////////////////////////////////////////////////
3683 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Vertex", "VERTEX" },
3684 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "UV", "UV" },
3685 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
3686 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
3687 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "Point Size", "POINT_SIZE" },
3688 ////////////////////////////////////////////////////////////////////////
3689 // Canvas Item, Fragment.
3690 ////////////////////////////////////////////////////////////////////////
3691 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR.rgb" },
3692 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "COLOR.a" },
3693 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal", "NORMAL" },
3694 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Normal Map", "NORMAL_MAP" },
3695 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "Normal Map Depth", "NORMAL_MAP_DEPTH" },
3696 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Light Vertex", "LIGHT_VERTEX" },
3697 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "Shadow Vertex", "SHADOW_VERTEX" },
3698 ////////////////////////////////////////////////////////////////////////
3699 // Canvas Item, Light.
3700 ////////////////////////////////////////////////////////////////////////
3701 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Light", "LIGHT.rgb" },
3702 { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "Light Alpha", "LIGHT.a" },
3703
3704 ////////////////////////////////////////////////////////////////////////
3705 // Sky, Sky.
3706 ////////////////////////////////////////////////////////////////////////
3707 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Color", "COLOR" },
3708 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "Alpha", "ALPHA" },
3709 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Fog", "FOG.rgb" },
3710 { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "Fog Alpha", "FOG.a" },
3711
3712 ////////////////////////////////////////////////////////////////////////
3713 // Fog, Fog.
3714 ////////////////////////////////////////////////////////////////////////
3715 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "Density", "DENSITY" },
3716 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" },
3717 { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Emission", "EMISSION" },
3718
3719 ////////////////////////////////////////////////////////////////////////
3720 { Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
3721};
3722
3723int VisualShaderNodeOutput::get_input_port_count() const {
3724 int idx = 0;
3725 int count = 0;
3726
3727 while (ports[idx].mode != Shader::MODE_MAX) {
3728 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3729 count++;
3730 }
3731 idx++;
3732 }
3733
3734 return count;
3735}
3736
3737VisualShaderNodeOutput::PortType VisualShaderNodeOutput::get_input_port_type(int p_port) const {
3738 int idx = 0;
3739 int count = 0;
3740
3741 while (ports[idx].mode != Shader::MODE_MAX) {
3742 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3743 if (count == p_port) {
3744 return ports[idx].type;
3745 }
3746 count++;
3747 }
3748 idx++;
3749 }
3750
3751 return PORT_TYPE_SCALAR;
3752}
3753
3754String VisualShaderNodeOutput::get_input_port_name(int p_port) const {
3755 int idx = 0;
3756 int count = 0;
3757
3758 while (ports[idx].mode != Shader::MODE_MAX) {
3759 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3760 if (count == p_port) {
3761 return String(ports[idx].name);
3762 }
3763 count++;
3764 }
3765 idx++;
3766 }
3767
3768 return String();
3769}
3770
3771Variant VisualShaderNodeOutput::get_input_port_default_value(int p_port) const {
3772 return Variant();
3773}
3774
3775int VisualShaderNodeOutput::get_output_port_count() const {
3776 return 0;
3777}
3778
3779VisualShaderNodeOutput::PortType VisualShaderNodeOutput::get_output_port_type(int p_port) const {
3780 return PORT_TYPE_SCALAR;
3781}
3782
3783String VisualShaderNodeOutput::get_output_port_name(int p_port) const {
3784 return String();
3785}
3786
3787bool VisualShaderNodeOutput::is_port_separator(int p_index) const {
3788 if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_VERTEX) {
3789 String port_name = get_input_port_name(p_index);
3790 return bool(port_name == "Model View Matrix");
3791 }
3792 if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) {
3793 String port_name = get_input_port_name(p_index);
3794 return bool(port_name == "AO" || port_name == "Normal" || port_name == "Rim" || port_name == "Clearcoat" || port_name == "Anisotropy" || port_name == "Subsurf Scatter" || port_name == "Alpha Scissor Threshold" || port_name == "Depth");
3795 }
3796 return false;
3797}
3798
3799String VisualShaderNodeOutput::get_caption() const {
3800 return "Output";
3801}
3802
3803String VisualShaderNodeOutput::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
3804 int idx = 0;
3805 int count = 0;
3806
3807 String shader_code;
3808 while (ports[idx].mode != Shader::MODE_MAX) {
3809 if (ports[idx].mode == shader_mode && ports[idx].shader_type == shader_type) {
3810 if (!p_input_vars[count].is_empty()) {
3811 String s = ports[idx].string;
3812 if (s.contains(":")) {
3813 shader_code += " " + s.get_slicec(':', 0) + " = " + p_input_vars[count] + "." + s.get_slicec(':', 1) + ";\n";
3814 } else {
3815 shader_code += " " + s + " = " + p_input_vars[count] + ";\n";
3816 }
3817 }
3818 count++;
3819 }
3820 idx++;
3821 }
3822
3823 return shader_code;
3824}
3825
3826VisualShaderNodeOutput::VisualShaderNodeOutput() {
3827}
3828
3829///////////////////////////
3830
3831void VisualShaderNodeParameter::set_parameter_name(const String &p_name) {
3832 parameter_name = p_name;
3833 emit_signal(SNAME("name_changed"));
3834 emit_changed();
3835}
3836
3837String VisualShaderNodeParameter::get_parameter_name() const {
3838 return parameter_name;
3839}
3840
3841void VisualShaderNodeParameter::set_qualifier(VisualShaderNodeParameter::Qualifier p_qual) {
3842 ERR_FAIL_INDEX(int(p_qual), int(QUAL_MAX));
3843 if (qualifier == p_qual) {
3844 return;
3845 }
3846 qualifier = p_qual;
3847 emit_changed();
3848}
3849
3850VisualShaderNodeParameter::Qualifier VisualShaderNodeParameter::get_qualifier() const {
3851 return qualifier;
3852}
3853
3854void VisualShaderNodeParameter::set_global_code_generated(bool p_enabled) {
3855 global_code_generated = p_enabled;
3856}
3857
3858bool VisualShaderNodeParameter::is_global_code_generated() const {
3859 return global_code_generated;
3860}
3861
3862#ifndef DISABLE_DEPRECATED
3863// Kept for compatibility from 3.x to 4.0.
3864bool VisualShaderNodeParameter::_set(const StringName &p_name, const Variant &p_value) {
3865 if (p_name == "uniform_name") {
3866 set_parameter_name(p_value);
3867 return true;
3868 }
3869 return false;
3870}
3871#endif
3872
3873void VisualShaderNodeParameter::_bind_methods() {
3874 ClassDB::bind_method(D_METHOD("set_parameter_name", "name"), &VisualShaderNodeParameter::set_parameter_name);
3875 ClassDB::bind_method(D_METHOD("get_parameter_name"), &VisualShaderNodeParameter::get_parameter_name);
3876
3877 ClassDB::bind_method(D_METHOD("set_qualifier", "qualifier"), &VisualShaderNodeParameter::set_qualifier);
3878 ClassDB::bind_method(D_METHOD("get_qualifier"), &VisualShaderNodeParameter::get_qualifier);
3879
3880 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "parameter_name"), "set_parameter_name", "get_parameter_name");
3881 ADD_PROPERTY(PropertyInfo(Variant::INT, "qualifier", PROPERTY_HINT_ENUM, "None,Global,Instance"), "set_qualifier", "get_qualifier");
3882
3883 BIND_ENUM_CONSTANT(QUAL_NONE);
3884 BIND_ENUM_CONSTANT(QUAL_GLOBAL);
3885 BIND_ENUM_CONSTANT(QUAL_INSTANCE);
3886 BIND_ENUM_CONSTANT(QUAL_MAX);
3887}
3888
3889String VisualShaderNodeParameter::_get_qual_str() const {
3890 if (is_qualifier_supported(qualifier)) {
3891 switch (qualifier) {
3892 case QUAL_NONE:
3893 break;
3894 case QUAL_GLOBAL:
3895 return "global ";
3896 case QUAL_INSTANCE:
3897 return "instance ";
3898 default:
3899 break;
3900 }
3901 }
3902 return String();
3903}
3904
3905String VisualShaderNodeParameter::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
3906 List<String> keyword_list;
3907 ShaderLanguage::get_keyword_list(&keyword_list);
3908 if (keyword_list.find(parameter_name)) {
3909 return RTR("Shader keywords cannot be used as parameter names.\nChoose another name.");
3910 }
3911 if (!is_qualifier_supported(qualifier)) {
3912 String qualifier_str;
3913 switch (qualifier) {
3914 case QUAL_NONE:
3915 break;
3916 case QUAL_GLOBAL:
3917 qualifier_str = "global";
3918 break;
3919 case QUAL_INSTANCE:
3920 qualifier_str = "instance";
3921 break;
3922 default:
3923 break;
3924 }
3925 return vformat(RTR("This parameter type does not support the '%s' qualifier."), qualifier_str);
3926 } else if (qualifier == Qualifier::QUAL_GLOBAL) {
3927 RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(parameter_name);
3928 if (gvt == RS::GLOBAL_VAR_TYPE_MAX) {
3929 return vformat(RTR("Global parameter '%s' does not exist.\nCreate it in the Project Settings."), parameter_name);
3930 }
3931 bool incompatible_type = false;
3932 switch (gvt) {
3933 case RS::GLOBAL_VAR_TYPE_FLOAT: {
3934 if (!Object::cast_to<VisualShaderNodeFloatParameter>(this)) {
3935 incompatible_type = true;
3936 }
3937 } break;
3938 case RS::GLOBAL_VAR_TYPE_INT: {
3939 if (!Object::cast_to<VisualShaderNodeIntParameter>(this)) {
3940 incompatible_type = true;
3941 }
3942 } break;
3943 case RS::GLOBAL_VAR_TYPE_BOOL: {
3944 if (!Object::cast_to<VisualShaderNodeBooleanParameter>(this)) {
3945 incompatible_type = true;
3946 }
3947 } break;
3948 case RS::GLOBAL_VAR_TYPE_COLOR: {
3949 if (!Object::cast_to<VisualShaderNodeColorParameter>(this)) {
3950 incompatible_type = true;
3951 }
3952 } break;
3953 case RS::GLOBAL_VAR_TYPE_VEC3: {
3954 if (!Object::cast_to<VisualShaderNodeVec3Parameter>(this)) {
3955 incompatible_type = true;
3956 }
3957 } break;
3958 case RS::GLOBAL_VAR_TYPE_VEC4: {
3959 if (!Object::cast_to<VisualShaderNodeVec4Parameter>(this)) {
3960 incompatible_type = true;
3961 }
3962 } break;
3963 case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
3964 if (!Object::cast_to<VisualShaderNodeTransformParameter>(this)) {
3965 incompatible_type = true;
3966 }
3967 } break;
3968 case RS::GLOBAL_VAR_TYPE_SAMPLER2D: {
3969 if (!Object::cast_to<VisualShaderNodeTextureParameter>(this)) {
3970 incompatible_type = true;
3971 }
3972 } break;
3973 case RS::GLOBAL_VAR_TYPE_SAMPLER3D: {
3974 if (!Object::cast_to<VisualShaderNodeTexture3DParameter>(this)) {
3975 incompatible_type = true;
3976 }
3977 } break;
3978 case RS::GLOBAL_VAR_TYPE_SAMPLER2DARRAY: {
3979 if (!Object::cast_to<VisualShaderNodeTexture2DArrayParameter>(this)) {
3980 incompatible_type = true;
3981 }
3982 } break;
3983 case RS::GLOBAL_VAR_TYPE_SAMPLERCUBE: {
3984 if (!Object::cast_to<VisualShaderNodeCubemapParameter>(this)) {
3985 incompatible_type = true;
3986 }
3987 } break;
3988 default:
3989 break;
3990 }
3991 if (incompatible_type) {
3992 return vformat(RTR("Global parameter '%s' has an incompatible type for this kind of node.\nChange it in the Project Settings."), parameter_name);
3993 }
3994 }
3995
3996 return String();
3997}
3998
3999Vector<StringName> VisualShaderNodeParameter::get_editable_properties() const {
4000 Vector<StringName> props;
4001 props.push_back("qualifier");
4002 return props;
4003}
4004
4005VisualShaderNodeParameter::VisualShaderNodeParameter() {
4006}
4007
4008////////////// ResizeableBase
4009
4010void VisualShaderNodeResizableBase::set_size(const Size2 &p_size) {
4011 size = p_size;
4012}
4013
4014Size2 VisualShaderNodeResizableBase::get_size() const {
4015 return size;
4016}
4017
4018void VisualShaderNodeResizableBase::set_allow_v_resize(bool p_enabled) {
4019 allow_v_resize = p_enabled;
4020}
4021
4022bool VisualShaderNodeResizableBase::is_allow_v_resize() const {
4023 return allow_v_resize;
4024}
4025
4026void VisualShaderNodeResizableBase::_bind_methods() {
4027 ClassDB::bind_method(D_METHOD("set_size", "size"), &VisualShaderNodeResizableBase::set_size);
4028 ClassDB::bind_method(D_METHOD("get_size"), &VisualShaderNodeResizableBase::get_size);
4029
4030 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
4031}
4032
4033VisualShaderNodeResizableBase::VisualShaderNodeResizableBase() {
4034 set_allow_v_resize(true);
4035}
4036
4037////////////// Comment
4038
4039String VisualShaderNodeComment::get_caption() const {
4040 return title;
4041}
4042
4043int VisualShaderNodeComment::get_input_port_count() const {
4044 return 0;
4045}
4046
4047VisualShaderNodeComment::PortType VisualShaderNodeComment::get_input_port_type(int p_port) const {
4048 return PortType::PORT_TYPE_SCALAR;
4049}
4050
4051String VisualShaderNodeComment::get_input_port_name(int p_port) const {
4052 return String();
4053}
4054
4055int VisualShaderNodeComment::get_output_port_count() const {
4056 return 0;
4057}
4058
4059VisualShaderNodeComment::PortType VisualShaderNodeComment::get_output_port_type(int p_port) const {
4060 return PortType::PORT_TYPE_SCALAR;
4061}
4062
4063String VisualShaderNodeComment::get_output_port_name(int p_port) const {
4064 return String();
4065}
4066
4067void VisualShaderNodeComment::set_title(const String &p_title) {
4068 title = p_title;
4069}
4070
4071String VisualShaderNodeComment::get_title() const {
4072 return title;
4073}
4074
4075void VisualShaderNodeComment::set_description(const String &p_description) {
4076 description = p_description;
4077}
4078
4079String VisualShaderNodeComment::get_description() const {
4080 return description;
4081}
4082
4083String VisualShaderNodeComment::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
4084 return String();
4085}
4086
4087void VisualShaderNodeComment::_bind_methods() {
4088 ClassDB::bind_method(D_METHOD("set_title", "title"), &VisualShaderNodeComment::set_title);
4089 ClassDB::bind_method(D_METHOD("get_title"), &VisualShaderNodeComment::get_title);
4090
4091 ClassDB::bind_method(D_METHOD("set_description", "description"), &VisualShaderNodeComment::set_description);
4092 ClassDB::bind_method(D_METHOD("get_description"), &VisualShaderNodeComment::get_description);
4093
4094 ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
4095 ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_description", "get_description");
4096}
4097
4098VisualShaderNodeComment::VisualShaderNodeComment() {
4099}
4100
4101////////////// GroupBase
4102
4103void VisualShaderNodeGroupBase::set_inputs(const String &p_inputs) {
4104 if (inputs == p_inputs) {
4105 return;
4106 }
4107
4108 clear_input_ports();
4109
4110 inputs = p_inputs;
4111
4112 Vector<String> input_strings = inputs.split(";", false);
4113
4114 int input_port_count = input_strings.size();
4115
4116 for (int i = 0; i < input_port_count; i++) {
4117 Vector<String> arr = input_strings[i].split(",");
4118 ERR_FAIL_COND(arr.size() != 3);
4119
4120 int port_idx = arr[0].to_int();
4121 int port_type = arr[1].to_int();
4122 String port_name = arr[2];
4123
4124 Port port;
4125 port.type = (PortType)port_type;
4126 port.name = port_name;
4127 input_ports[port_idx] = port;
4128 }
4129}
4130
4131String VisualShaderNodeGroupBase::get_inputs() const {
4132 return inputs;
4133}
4134
4135void VisualShaderNodeGroupBase::set_outputs(const String &p_outputs) {
4136 if (outputs == p_outputs) {
4137 return;
4138 }
4139
4140 clear_output_ports();
4141
4142 outputs = p_outputs;
4143
4144 Vector<String> output_strings = outputs.split(";", false);
4145
4146 int output_port_count = output_strings.size();
4147
4148 for (int i = 0; i < output_port_count; i++) {
4149 Vector<String> arr = output_strings[i].split(",");
4150 ERR_FAIL_COND(arr.size() != 3);
4151
4152 int port_idx = arr[0].to_int();
4153 int port_type = arr[1].to_int();
4154 String port_name = arr[2];
4155
4156 Port port;
4157 port.type = (PortType)port_type;
4158 port.name = port_name;
4159 output_ports[port_idx] = port;
4160 }
4161}
4162
4163String VisualShaderNodeGroupBase::get_outputs() const {
4164 return outputs;
4165}
4166
4167bool VisualShaderNodeGroupBase::is_valid_port_name(const String &p_name) const {
4168 if (!p_name.is_valid_identifier()) {
4169 return false;
4170 }
4171 for (int i = 0; i < get_input_port_count(); i++) {
4172 if (get_input_port_name(i) == p_name) {
4173 return false;
4174 }
4175 }
4176 for (int i = 0; i < get_output_port_count(); i++) {
4177 if (get_output_port_name(i) == p_name) {
4178 return false;
4179 }
4180 }
4181 return true;
4182}
4183
4184void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const String &p_name) {
4185 ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX));
4186 ERR_FAIL_COND(!is_valid_port_name(p_name));
4187
4188 String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";";
4189 Vector<String> inputs_strings = inputs.split(";", false);
4190 int index = 0;
4191 if (p_id < inputs_strings.size()) {
4192 for (int i = 0; i < inputs_strings.size(); i++) {
4193 if (i == p_id) {
4194 inputs = inputs.insert(index, str);
4195 break;
4196 }
4197 index += inputs_strings[i].size();
4198 }
4199 } else {
4200 inputs += str;
4201 }
4202
4203 inputs_strings = inputs.split(";", false);
4204 index = 0;
4205
4206 for (int i = 0; i < inputs_strings.size(); i++) {
4207 int count = 0;
4208 for (int j = 0; j < inputs_strings[i].size(); j++) {
4209 if (inputs_strings[i][j] == ',') {
4210 break;
4211 }
4212 count++;
4213 }
4214
4215 inputs = inputs.left(index) + inputs.substr(index + count);
4216 inputs = inputs.insert(index, itos(i));
4217 index += inputs_strings[i].size();
4218 }
4219
4220 _apply_port_changes();
4221 emit_changed();
4222}
4223
4224void VisualShaderNodeGroupBase::remove_input_port(int p_id) {
4225 ERR_FAIL_COND(!has_input_port(p_id));
4226
4227 Vector<String> inputs_strings = inputs.split(";", false);
4228 int count = 0;
4229 int index = 0;
4230 for (int i = 0; i < inputs_strings.size(); i++) {
4231 Vector<String> arr = inputs_strings[i].split(",");
4232 if (arr[0].to_int() == p_id) {
4233 count = inputs_strings[i].size();
4234 break;
4235 }
4236 index += inputs_strings[i].size();
4237 }
4238 inputs = inputs.left(index) + inputs.substr(index + count);
4239
4240 inputs_strings = inputs.split(";", false);
4241 inputs = inputs.substr(0, index);
4242
4243 for (int i = p_id; i < inputs_strings.size(); i++) {
4244 inputs += inputs_strings[i].replace_first(inputs_strings[i].split(",")[0], itos(i)) + ";";
4245 }
4246
4247 _apply_port_changes();
4248 emit_changed();
4249}
4250
4251int VisualShaderNodeGroupBase::get_input_port_count() const {
4252 return input_ports.size();
4253}
4254
4255bool VisualShaderNodeGroupBase::has_input_port(int p_id) const {
4256 return input_ports.has(p_id);
4257}
4258
4259void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const String &p_name) {
4260 ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX));
4261 ERR_FAIL_COND(!is_valid_port_name(p_name));
4262
4263 String str = itos(p_id) + "," + itos(p_type) + "," + p_name + ";";
4264 Vector<String> outputs_strings = outputs.split(";", false);
4265 int index = 0;
4266 if (p_id < outputs_strings.size()) {
4267 for (int i = 0; i < outputs_strings.size(); i++) {
4268 if (i == p_id) {
4269 outputs = outputs.insert(index, str);
4270 break;
4271 }
4272 index += outputs_strings[i].size();
4273 }
4274 } else {
4275 outputs += str;
4276 }
4277
4278 outputs_strings = outputs.split(";", false);
4279 index = 0;
4280
4281 for (int i = 0; i < outputs_strings.size(); i++) {
4282 int count = 0;
4283 for (int j = 0; j < outputs_strings[i].size(); j++) {
4284 if (outputs_strings[i][j] == ',') {
4285 break;
4286 }
4287 count++;
4288 }
4289
4290 outputs = outputs.left(index) + outputs.substr(index + count);
4291 outputs = outputs.insert(index, itos(i));
4292 index += outputs_strings[i].size();
4293 }
4294
4295 _apply_port_changes();
4296 emit_changed();
4297}
4298
4299void VisualShaderNodeGroupBase::remove_output_port(int p_id) {
4300 ERR_FAIL_COND(!has_output_port(p_id));
4301
4302 Vector<String> outputs_strings = outputs.split(";", false);
4303 int count = 0;
4304 int index = 0;
4305 for (int i = 0; i < outputs_strings.size(); i++) {
4306 Vector<String> arr = outputs_strings[i].split(",");
4307 if (arr[0].to_int() == p_id) {
4308 count = outputs_strings[i].size();
4309 break;
4310 }
4311 index += outputs_strings[i].size();
4312 }
4313 outputs = outputs.left(index) + outputs.substr(index + count);
4314
4315 outputs_strings = outputs.split(";", false);
4316 outputs = outputs.substr(0, index);
4317
4318 for (int i = p_id; i < outputs_strings.size(); i++) {
4319 outputs += outputs_strings[i].replace_first(outputs_strings[i].split(",")[0], itos(i)) + ";";
4320 }
4321
4322 _apply_port_changes();
4323 emit_changed();
4324}
4325
4326int VisualShaderNodeGroupBase::get_output_port_count() const {
4327 return output_ports.size();
4328}
4329
4330bool VisualShaderNodeGroupBase::has_output_port(int p_id) const {
4331 return output_ports.has(p_id);
4332}
4333
4334void VisualShaderNodeGroupBase::clear_input_ports() {
4335 input_ports.clear();
4336}
4337
4338void VisualShaderNodeGroupBase::clear_output_ports() {
4339 output_ports.clear();
4340}
4341
4342void VisualShaderNodeGroupBase::set_input_port_type(int p_id, int p_type) {
4343 ERR_FAIL_COND(!has_input_port(p_id));
4344 ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX));
4345
4346 if (input_ports[p_id].type == p_type) {
4347 return;
4348 }
4349
4350 Vector<String> inputs_strings = inputs.split(";", false);
4351 int count = 0;
4352 int index = 0;
4353 for (int i = 0; i < inputs_strings.size(); i++) {
4354 Vector<String> arr = inputs_strings[i].split(",");
4355 ERR_FAIL_COND(arr.size() != 3);
4356
4357 if (arr[0].to_int() == p_id) {
4358 index += arr[0].size();
4359 count = arr[1].size() - 1;
4360 break;
4361 }
4362 index += inputs_strings[i].size();
4363 }
4364
4365 inputs = inputs.left(index) + inputs.substr(index + count);
4366 inputs = inputs.insert(index, itos(p_type));
4367
4368 _apply_port_changes();
4369 emit_changed();
4370}
4371
4372VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_input_port_type(int p_id) const {
4373 ERR_FAIL_COND_V(!input_ports.has(p_id), (PortType)0);
4374 return input_ports[p_id].type;
4375}
4376
4377void VisualShaderNodeGroupBase::set_input_port_name(int p_id, const String &p_name) {
4378 ERR_FAIL_COND(!has_input_port(p_id));
4379 ERR_FAIL_COND(!is_valid_port_name(p_name));
4380
4381 if (input_ports[p_id].name == p_name) {
4382 return;
4383 }
4384
4385 Vector<String> inputs_strings = inputs.split(";", false);
4386 int count = 0;
4387 int index = 0;
4388 for (int i = 0; i < inputs_strings.size(); i++) {
4389 Vector<String> arr = inputs_strings[i].split(",");
4390 ERR_FAIL_COND(arr.size() != 3);
4391
4392 if (arr[0].to_int() == p_id) {
4393 index += arr[0].size() + arr[1].size();
4394 count = arr[2].size() - 1;
4395 break;
4396 }
4397 index += inputs_strings[i].size();
4398 }
4399
4400 inputs = inputs.left(index) + inputs.substr(index + count);
4401 inputs = inputs.insert(index, p_name);
4402
4403 _apply_port_changes();
4404 emit_changed();
4405}
4406
4407String VisualShaderNodeGroupBase::get_input_port_name(int p_id) const {
4408 ERR_FAIL_COND_V(!input_ports.has(p_id), "");
4409 return input_ports[p_id].name;
4410}
4411
4412void VisualShaderNodeGroupBase::set_output_port_type(int p_id, int p_type) {
4413 ERR_FAIL_COND(!has_output_port(p_id));
4414 ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX));
4415
4416 if (output_ports[p_id].type == p_type) {
4417 return;
4418 }
4419
4420 Vector<String> output_strings = outputs.split(";", false);
4421 int count = 0;
4422 int index = 0;
4423 for (int i = 0; i < output_strings.size(); i++) {
4424 Vector<String> arr = output_strings[i].split(",");
4425 ERR_FAIL_COND(arr.size() != 3);
4426
4427 if (arr[0].to_int() == p_id) {
4428 index += arr[0].size();
4429 count = arr[1].size() - 1;
4430 break;
4431 }
4432 index += output_strings[i].size();
4433 }
4434
4435 outputs = outputs.left(index) + outputs.substr(index + count);
4436
4437 outputs = outputs.insert(index, itos(p_type));
4438
4439 _apply_port_changes();
4440 emit_changed();
4441}
4442
4443VisualShaderNodeGroupBase::PortType VisualShaderNodeGroupBase::get_output_port_type(int p_id) const {
4444 ERR_FAIL_COND_V(!output_ports.has(p_id), (PortType)0);
4445 return output_ports[p_id].type;
4446}
4447
4448void VisualShaderNodeGroupBase::set_output_port_name(int p_id, const String &p_name) {
4449 ERR_FAIL_COND(!has_output_port(p_id));
4450 ERR_FAIL_COND(!is_valid_port_name(p_name));
4451
4452 if (output_ports[p_id].name == p_name) {
4453 return;
4454 }
4455
4456 Vector<String> output_strings = outputs.split(";", false);
4457 int count = 0;
4458 int index = 0;
4459 for (int i = 0; i < output_strings.size(); i++) {
4460 Vector<String> arr = output_strings[i].split(",");
4461 ERR_FAIL_COND(arr.size() != 3);
4462
4463 if (arr[0].to_int() == p_id) {
4464 index += arr[0].size() + arr[1].size();
4465 count = arr[2].size() - 1;
4466 break;
4467 }
4468 index += output_strings[i].size();
4469 }
4470
4471 outputs = outputs.left(index) + outputs.substr(index + count);
4472
4473 outputs = outputs.insert(index, p_name);
4474
4475 _apply_port_changes();
4476 emit_changed();
4477}
4478
4479String VisualShaderNodeGroupBase::get_output_port_name(int p_id) const {
4480 ERR_FAIL_COND_V(!output_ports.has(p_id), "");
4481 return output_ports[p_id].name;
4482}
4483
4484int VisualShaderNodeGroupBase::get_free_input_port_id() const {
4485 return input_ports.size();
4486}
4487
4488int VisualShaderNodeGroupBase::get_free_output_port_id() const {
4489 return output_ports.size();
4490}
4491
4492void VisualShaderNodeGroupBase::set_ctrl_pressed(Control *p_control, int p_index) {
4493 controls[p_index] = p_control;
4494}
4495
4496Control *VisualShaderNodeGroupBase::is_ctrl_pressed(int p_index) {
4497 ERR_FAIL_COND_V(!controls.has(p_index), nullptr);
4498 return controls[p_index];
4499}
4500
4501void VisualShaderNodeGroupBase::_apply_port_changes() {
4502 Vector<String> inputs_strings = inputs.split(";", false);
4503 Vector<String> outputs_strings = outputs.split(";", false);
4504
4505 clear_input_ports();
4506 clear_output_ports();
4507
4508 for (int i = 0; i < inputs_strings.size(); i++) {
4509 Vector<String> arr = inputs_strings[i].split(",");
4510 ERR_FAIL_COND(arr.size() != 3);
4511
4512 Port port;
4513 port.type = (PortType)arr[1].to_int();
4514 port.name = arr[2];
4515 input_ports[i] = port;
4516 }
4517 for (int i = 0; i < outputs_strings.size(); i++) {
4518 Vector<String> arr = outputs_strings[i].split(",");
4519 ERR_FAIL_COND(arr.size() != 3);
4520
4521 Port port;
4522 port.type = (PortType)arr[1].to_int();
4523 port.name = arr[2];
4524 output_ports[i] = port;
4525 }
4526}
4527
4528void VisualShaderNodeGroupBase::set_editable(bool p_enabled) {
4529 editable = p_enabled;
4530}
4531
4532bool VisualShaderNodeGroupBase::is_editable() const {
4533 return editable;
4534}
4535
4536void VisualShaderNodeGroupBase::_bind_methods() {
4537 ClassDB::bind_method(D_METHOD("set_inputs", "inputs"), &VisualShaderNodeGroupBase::set_inputs);
4538 ClassDB::bind_method(D_METHOD("get_inputs"), &VisualShaderNodeGroupBase::get_inputs);
4539
4540 ClassDB::bind_method(D_METHOD("set_outputs", "outputs"), &VisualShaderNodeGroupBase::set_outputs);
4541 ClassDB::bind_method(D_METHOD("get_outputs"), &VisualShaderNodeGroupBase::get_outputs);
4542
4543 ClassDB::bind_method(D_METHOD("is_valid_port_name", "name"), &VisualShaderNodeGroupBase::is_valid_port_name);
4544
4545 ClassDB::bind_method(D_METHOD("add_input_port", "id", "type", "name"), &VisualShaderNodeGroupBase::add_input_port);
4546 ClassDB::bind_method(D_METHOD("remove_input_port", "id"), &VisualShaderNodeGroupBase::remove_input_port);
4547 ClassDB::bind_method(D_METHOD("get_input_port_count"), &VisualShaderNodeGroupBase::get_input_port_count);
4548 ClassDB::bind_method(D_METHOD("has_input_port", "id"), &VisualShaderNodeGroupBase::has_input_port);
4549 ClassDB::bind_method(D_METHOD("clear_input_ports"), &VisualShaderNodeGroupBase::clear_input_ports);
4550
4551 ClassDB::bind_method(D_METHOD("add_output_port", "id", "type", "name"), &VisualShaderNodeGroupBase::add_output_port);
4552 ClassDB::bind_method(D_METHOD("remove_output_port", "id"), &VisualShaderNodeGroupBase::remove_output_port);
4553 ClassDB::bind_method(D_METHOD("get_output_port_count"), &VisualShaderNodeGroupBase::get_output_port_count);
4554 ClassDB::bind_method(D_METHOD("has_output_port", "id"), &VisualShaderNodeGroupBase::has_output_port);
4555 ClassDB::bind_method(D_METHOD("clear_output_ports"), &VisualShaderNodeGroupBase::clear_output_ports);
4556
4557 ClassDB::bind_method(D_METHOD("set_input_port_name", "id", "name"), &VisualShaderNodeGroupBase::set_input_port_name);
4558 ClassDB::bind_method(D_METHOD("set_input_port_type", "id", "type"), &VisualShaderNodeGroupBase::set_input_port_type);
4559 ClassDB::bind_method(D_METHOD("set_output_port_name", "id", "name"), &VisualShaderNodeGroupBase::set_output_port_name);
4560 ClassDB::bind_method(D_METHOD("set_output_port_type", "id", "type"), &VisualShaderNodeGroupBase::set_output_port_type);
4561
4562 ClassDB::bind_method(D_METHOD("get_free_input_port_id"), &VisualShaderNodeGroupBase::get_free_input_port_id);
4563 ClassDB::bind_method(D_METHOD("get_free_output_port_id"), &VisualShaderNodeGroupBase::get_free_output_port_id);
4564}
4565
4566String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
4567 return "";
4568}
4569
4570VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() {
4571 simple_decl = false;
4572}
4573
4574////////////// Expression
4575
4576String VisualShaderNodeExpression::get_caption() const {
4577 return "Expression";
4578}
4579
4580void VisualShaderNodeExpression::set_expression(const String &p_expression) {
4581 expression = p_expression;
4582 emit_changed();
4583}
4584
4585String VisualShaderNodeExpression::get_expression() const {
4586 return expression;
4587}
4588
4589String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
4590 String _expression = expression;
4591
4592 _expression = _expression.insert(0, "\n");
4593 _expression = _expression.replace("\n", "\n ");
4594
4595 static Vector<String> pre_symbols;
4596 if (pre_symbols.is_empty()) {
4597 pre_symbols.push_back(" ");
4598 pre_symbols.push_back(",");
4599 pre_symbols.push_back(";");
4600 pre_symbols.push_back("{");
4601 pre_symbols.push_back("[");
4602 pre_symbols.push_back("]");
4603 pre_symbols.push_back("(");
4604 pre_symbols.push_back(" ");
4605 pre_symbols.push_back("-");
4606 pre_symbols.push_back("*");
4607 pre_symbols.push_back("/");
4608 pre_symbols.push_back("+");
4609 pre_symbols.push_back("=");
4610 pre_symbols.push_back("&");
4611 pre_symbols.push_back("|");
4612 pre_symbols.push_back("!");
4613 }
4614
4615 static Vector<String> post_symbols;
4616 if (post_symbols.is_empty()) {
4617 post_symbols.push_back(" ");
4618 post_symbols.push_back("\n");
4619 post_symbols.push_back(",");
4620 post_symbols.push_back(";");
4621 post_symbols.push_back("}");
4622 post_symbols.push_back("[");
4623 post_symbols.push_back("]");
4624 post_symbols.push_back(")");
4625 post_symbols.push_back(" ");
4626 post_symbols.push_back(".");
4627 post_symbols.push_back("-");
4628 post_symbols.push_back("*");
4629 post_symbols.push_back("/");
4630 post_symbols.push_back("+");
4631 post_symbols.push_back("=");
4632 post_symbols.push_back("&");
4633 post_symbols.push_back("|");
4634 post_symbols.push_back("!");
4635 }
4636
4637 for (int i = 0; i < get_input_port_count(); i++) {
4638 for (int j = 0; j < pre_symbols.size(); j++) {
4639 for (int k = 0; k < post_symbols.size(); k++) {
4640 _expression = _expression.replace(pre_symbols[j] + get_input_port_name(i) + post_symbols[k], pre_symbols[j] + p_input_vars[i] + post_symbols[k]);
4641 }
4642 }
4643 }
4644 for (int i = 0; i < get_output_port_count(); i++) {
4645 for (int j = 0; j < pre_symbols.size(); j++) {
4646 for (int k = 0; k < post_symbols.size(); k++) {
4647 _expression = _expression.replace(pre_symbols[j] + get_output_port_name(i) + post_symbols[k], pre_symbols[j] + p_output_vars[i] + post_symbols[k]);
4648 }
4649 }
4650 }
4651
4652 String output_initializer;
4653
4654 for (int i = 0; i < get_output_port_count(); i++) {
4655 int port_type = get_output_port_type(i);
4656 String tk = "";
4657 switch (port_type) {
4658 case PORT_TYPE_SCALAR:
4659 tk = "0.0";
4660 break;
4661 case PORT_TYPE_SCALAR_INT:
4662 tk = "0";
4663 break;
4664 case PORT_TYPE_VECTOR_2D:
4665 tk = "vec2(0.0, 0.0)";
4666 break;
4667 case PORT_TYPE_VECTOR_3D:
4668 tk = "vec3(0.0, 0.0, 0.0)";
4669 break;
4670 case PORT_TYPE_VECTOR_4D:
4671 tk = "vec4(0.0, 0.0, 0.0, 0.0)";
4672 break;
4673 case PORT_TYPE_BOOLEAN:
4674 tk = "false";
4675 break;
4676 case PORT_TYPE_TRANSFORM:
4677 tk = "mat4(1.0)";
4678 break;
4679 default:
4680 continue;
4681 }
4682 output_initializer += " " + p_output_vars[i] + " = " + tk + ";\n";
4683 }
4684
4685 String code;
4686 code += output_initializer;
4687 code += " {";
4688 code += _expression;
4689 code += "\n }\n";
4690
4691 return code;
4692}
4693
4694void VisualShaderNodeExpression::_bind_methods() {
4695 ClassDB::bind_method(D_METHOD("set_expression", "expression"), &VisualShaderNodeExpression::set_expression);
4696 ClassDB::bind_method(D_METHOD("get_expression"), &VisualShaderNodeExpression::get_expression);
4697
4698 ADD_PROPERTY(PropertyInfo(Variant::STRING, "expression"), "set_expression", "get_expression");
4699}
4700
4701VisualShaderNodeExpression::VisualShaderNodeExpression() {
4702 set_editable(true);
4703}
4704
4705////////////// Global Expression
4706
4707String VisualShaderNodeGlobalExpression::get_caption() const {
4708 return "GlobalExpression";
4709}
4710
4711String VisualShaderNodeGlobalExpression::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
4712 return expression;
4713}
4714
4715VisualShaderNodeGlobalExpression::VisualShaderNodeGlobalExpression() {
4716 set_editable(false);
4717}
4718
4719////////////// Varying
4720
4721List<VisualShaderNodeVarying::Varying> varyings;
4722
4723void VisualShaderNodeVarying::add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) { // static
4724 varyings.push_back({ p_name, p_mode, p_type });
4725}
4726
4727void VisualShaderNodeVarying::clear_varyings() { // static
4728 varyings.clear();
4729}
4730
4731bool VisualShaderNodeVarying::has_varying(const String &p_name) { // static
4732 for (const VisualShaderNodeVarying::Varying &E : varyings) {
4733 if (E.name == p_name) {
4734 return true;
4735 }
4736 }
4737 return false;
4738}
4739
4740int VisualShaderNodeVarying::get_varyings_count() const {
4741 return varyings.size();
4742}
4743
4744String VisualShaderNodeVarying::get_varying_name_by_index(int p_idx) const {
4745 if (p_idx >= 0 && p_idx < varyings.size()) {
4746 return varyings[p_idx].name;
4747 }
4748 return "";
4749}
4750
4751VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_name(const String &p_name) const {
4752 for (int i = 0; i < varyings.size(); i++) {
4753 if (varyings[i].name == p_name) {
4754 return varyings[i].type;
4755 }
4756 }
4757 return VisualShader::VARYING_TYPE_FLOAT;
4758}
4759
4760VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_index(int p_idx) const {
4761 if (p_idx >= 0 && p_idx < varyings.size()) {
4762 return varyings[p_idx].type;
4763 }
4764 return VisualShader::VARYING_TYPE_FLOAT;
4765}
4766
4767VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_name(const String &p_name) const {
4768 for (int i = 0; i < varyings.size(); i++) {
4769 if (varyings[i].name == p_name) {
4770 return varyings[i].mode;
4771 }
4772 }
4773 return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
4774}
4775
4776VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_index(int p_idx) const {
4777 if (p_idx >= 0 && p_idx < varyings.size()) {
4778 return varyings[p_idx].mode;
4779 }
4780 return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
4781}
4782
4783VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type_by_index(int p_idx) const {
4784 if (p_idx >= 0 && p_idx < varyings.size()) {
4785 return get_port_type(varyings[p_idx].type, 0);
4786 }
4787 return PORT_TYPE_SCALAR;
4788}
4789
4790//////////////
4791
4792void VisualShaderNodeVarying::_bind_methods() {
4793 ClassDB::bind_method(D_METHOD("set_varying_name", "name"), &VisualShaderNodeVarying::set_varying_name);
4794 ClassDB::bind_method(D_METHOD("get_varying_name"), &VisualShaderNodeVarying::get_varying_name);
4795
4796 ClassDB::bind_method(D_METHOD("set_varying_type", "type"), &VisualShaderNodeVarying::set_varying_type);
4797 ClassDB::bind_method(D_METHOD("get_varying_type"), &VisualShaderNodeVarying::get_varying_type);
4798
4799 ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "varying_name"), "set_varying_name", "get_varying_name");
4800 ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4,Boolean,Transform"), "set_varying_type", "get_varying_type");
4801}
4802
4803String VisualShaderNodeVarying::get_type_str() const {
4804 switch (varying_type) {
4805 case VisualShader::VARYING_TYPE_FLOAT:
4806 return "float";
4807 case VisualShader::VARYING_TYPE_INT:
4808 return "int";
4809 case VisualShader::VARYING_TYPE_UINT:
4810 return "uint";
4811 case VisualShader::VARYING_TYPE_VECTOR_2D:
4812 return "vec2";
4813 case VisualShader::VARYING_TYPE_VECTOR_3D:
4814 return "vec3";
4815 case VisualShader::VARYING_TYPE_VECTOR_4D:
4816 return "vec4";
4817 case VisualShader::VARYING_TYPE_BOOLEAN:
4818 return "bool";
4819 case VisualShader::VARYING_TYPE_TRANSFORM:
4820 return "mat4";
4821 default:
4822 break;
4823 }
4824 return "";
4825}
4826
4827VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualShader::VaryingType p_type, int p_port) const {
4828 switch (p_type) {
4829 case VisualShader::VARYING_TYPE_INT:
4830 return PORT_TYPE_SCALAR_INT;
4831 case VisualShader::VARYING_TYPE_UINT:
4832 return PORT_TYPE_SCALAR_UINT;
4833 case VisualShader::VARYING_TYPE_VECTOR_2D:
4834 return PORT_TYPE_VECTOR_2D;
4835 case VisualShader::VARYING_TYPE_VECTOR_3D:
4836 return PORT_TYPE_VECTOR_3D;
4837 case VisualShader::VARYING_TYPE_VECTOR_4D:
4838 return PORT_TYPE_VECTOR_4D;
4839 case VisualShader::VARYING_TYPE_BOOLEAN:
4840 return PORT_TYPE_BOOLEAN;
4841 case VisualShader::VARYING_TYPE_TRANSFORM:
4842 return PORT_TYPE_TRANSFORM;
4843 default:
4844 break;
4845 }
4846 return PORT_TYPE_SCALAR;
4847}
4848
4849void VisualShaderNodeVarying::set_varying_name(String p_varying_name) {
4850 if (varying_name == p_varying_name) {
4851 return;
4852 }
4853 varying_name = p_varying_name;
4854 emit_changed();
4855}
4856
4857String VisualShaderNodeVarying::get_varying_name() const {
4858 return varying_name;
4859}
4860
4861void VisualShaderNodeVarying::set_varying_type(VisualShader::VaryingType p_varying_type) {
4862 ERR_FAIL_INDEX(p_varying_type, VisualShader::VARYING_TYPE_MAX);
4863 if (varying_type == p_varying_type) {
4864 return;
4865 }
4866 varying_type = p_varying_type;
4867 emit_changed();
4868}
4869
4870VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type() const {
4871 return varying_type;
4872}
4873
4874VisualShaderNodeVarying::VisualShaderNodeVarying() {
4875}
4876
4877////////////// Varying Setter
4878
4879String VisualShaderNodeVaryingSetter::get_caption() const {
4880 return "VaryingSetter";
4881}
4882
4883int VisualShaderNodeVaryingSetter::get_input_port_count() const {
4884 return 1;
4885}
4886
4887VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_input_port_type(int p_port) const {
4888 return get_port_type(varying_type, p_port);
4889}
4890
4891String VisualShaderNodeVaryingSetter::get_input_port_name(int p_port) const {
4892 return "";
4893}
4894
4895int VisualShaderNodeVaryingSetter::get_output_port_count() const {
4896 return 0;
4897}
4898
4899VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_output_port_type(int p_port) const {
4900 return PORT_TYPE_SCALAR;
4901}
4902
4903String VisualShaderNodeVaryingSetter::get_output_port_name(int p_port) const {
4904 return "";
4905}
4906
4907String VisualShaderNodeVaryingSetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
4908 String code;
4909 if (varying_name == "[None]") {
4910 return code;
4911 }
4912 code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]);
4913 return code;
4914}
4915
4916VisualShaderNodeVaryingSetter::VisualShaderNodeVaryingSetter() {
4917}
4918
4919////////////// Varying Getter
4920
4921String VisualShaderNodeVaryingGetter::get_caption() const {
4922 return "VaryingGetter";
4923}
4924
4925int VisualShaderNodeVaryingGetter::get_input_port_count() const {
4926 return 0;
4927}
4928
4929VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_input_port_type(int p_port) const {
4930 return PORT_TYPE_SCALAR;
4931}
4932
4933String VisualShaderNodeVaryingGetter::get_input_port_name(int p_port) const {
4934 return "";
4935}
4936
4937int VisualShaderNodeVaryingGetter::get_output_port_count() const {
4938 return 1;
4939}
4940
4941VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_output_port_type(int p_port) const {
4942 return get_port_type(varying_type, p_port);
4943}
4944
4945String VisualShaderNodeVaryingGetter::get_output_port_name(int p_port) const {
4946 return "";
4947}
4948
4949bool VisualShaderNodeVaryingGetter::has_output_port_preview(int p_port) const {
4950 return false;
4951}
4952
4953String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
4954 String from = varying_name;
4955 String from2;
4956
4957 if (varying_name == "[None]") {
4958 switch (varying_type) {
4959 case VisualShader::VARYING_TYPE_FLOAT:
4960 from = "0.0";
4961 break;
4962 case VisualShader::VARYING_TYPE_INT:
4963 from = "0";
4964 break;
4965 case VisualShader::VARYING_TYPE_UINT:
4966 from = "0u";
4967 break;
4968 case VisualShader::VARYING_TYPE_VECTOR_2D:
4969 from = "vec2(0.0)";
4970 break;
4971 case VisualShader::VARYING_TYPE_VECTOR_3D:
4972 from = "vec3(0.0)";
4973 break;
4974 case VisualShader::VARYING_TYPE_VECTOR_4D:
4975 from = "vec4(0.0)";
4976 break;
4977 case VisualShader::VARYING_TYPE_BOOLEAN:
4978 from = "false";
4979 break;
4980 case VisualShader::VARYING_TYPE_TRANSFORM:
4981 from = "mat4(1.0)";
4982 break;
4983 default:
4984 break;
4985 }
4986 }
4987 return vformat(" %s = %s;\n", p_output_vars[0], from);
4988}
4989
4990VisualShaderNodeVaryingGetter::VisualShaderNodeVaryingGetter() {
4991 varying_name = "[None]";
4992}
4993