Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/shader/visual_shader_editor_plugin.cpp
21005 views
1
/**************************************************************************/
2
/* visual_shader_editor_plugin.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 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_editor_plugin.h"
32
33
#include "core/config/project_settings.h"
34
#include "core/input/input.h"
35
#include "core/io/resource_loader.h"
36
#include "core/math/math_defs.h"
37
#include "core/os/keyboard.h"
38
#include "core/version_generated.gen.h"
39
#include "editor/docks/filesystem_dock.h"
40
#include "editor/docks/inspector_dock.h"
41
#include "editor/editor_node.h"
42
#include "editor/editor_string_names.h"
43
#include "editor/editor_undo_redo_manager.h"
44
#include "editor/file_system/editor_paths.h"
45
#include "editor/gui/editor_toaster.h"
46
#include "editor/gui/filter_line_edit.h"
47
#include "editor/inspector/editor_properties_vector.h"
48
#include "editor/scene/curve_editor_plugin.h"
49
#include "editor/scene/material_editor_plugin.h"
50
#include "editor/settings/editor_settings.h"
51
#include "editor/shader/shader_editor_plugin.h"
52
#include "editor/themes/editor_scale.h"
53
#include "editor/themes/editor_theme_manager.h"
54
#include "scene/animation/tween.h"
55
#include "scene/gui/button.h"
56
#include "scene/gui/check_box.h"
57
#include "scene/gui/code_edit.h"
58
#include "scene/gui/color_picker.h"
59
#include "scene/gui/flow_container.h"
60
#include "scene/gui/graph_edit.h"
61
#include "scene/gui/menu_button.h"
62
#include "scene/gui/option_button.h"
63
#include "scene/gui/popup.h"
64
#include "scene/gui/rich_text_label.h"
65
#include "scene/gui/separator.h"
66
#include "scene/gui/split_container.h"
67
#include "scene/gui/texture_rect.h"
68
#include "scene/gui/tree.h"
69
#include "scene/gui/view_panner.h"
70
#include "scene/main/window.h"
71
#include "scene/resources/curve_texture.h"
72
#include "scene/resources/sky.h"
73
#include "scene/resources/style_box_flat.h"
74
#include "scene/resources/visual_shader_nodes.h"
75
#include "scene/resources/visual_shader_particle_nodes.h"
76
#include "servers/display/display_server.h"
77
#include "servers/rendering/shader_preprocessor.h"
78
#include "servers/rendering/shader_types.h"
79
80
struct FloatConstantDef {
81
String name;
82
float value = 0;
83
const char *desc_key;
84
};
85
86
static FloatConstantDef float_constant_defs[] = {
87
{ "E", Math::E, TTRC("E constant (2.718282). Represents the base of the natural logarithm.") },
88
{ "Epsilon", CMP_EPSILON, TTRC("Epsilon constant (0.00001). Smallest possible scalar number.") },
89
{ "Phi", 1.618034f, TTRC("Phi constant (1.618034). Golden ratio.") },
90
{ "Pi/4", Math::PI / 4, TTRC("Pi/4 constant (0.785398) or 45 degrees.") },
91
{ "Pi/2", Math::PI / 2, TTRC("Pi/2 constant (1.570796) or 90 degrees.") },
92
{ "Pi", Math::PI, TTRC("Pi constant (3.141593) or 180 degrees.") },
93
{ "Tau", Math::TAU, TTRC("Tau constant (6.283185) or 360 degrees.") },
94
{ "Sqrt2", Math::SQRT2, TTRC("Sqrt2 constant (1.414214). Square root of 2.") }
95
};
96
97
constexpr int MAX_FLOAT_CONST_DEFS = std_size(float_constant_defs);
98
99
///////////////////
100
101
void VisualShaderNodePlugin::set_editor(VisualShaderEditor *p_editor) {
102
vseditor = p_editor;
103
}
104
105
Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
106
Object *ret = nullptr;
107
GDVIRTUAL_CALL(_create_editor, p_parent_resource, p_node, ret);
108
return Object::cast_to<Control>(ret);
109
}
110
111
void VisualShaderNodePlugin::_bind_methods() {
112
GDVIRTUAL_BIND(_create_editor, "parent_resource", "visual_shader_node");
113
}
114
115
///////////////////
116
117
void VSGraphNode::_draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color, const Color &p_rim_color) {
118
Ref<Texture2D> port_icon = p_left ? get_slot_custom_icon_left(p_slot_index) : get_slot_custom_icon_right(p_slot_index);
119
120
Point2 icon_offset;
121
if (port_icon.is_null()) {
122
port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
123
}
124
125
icon_offset = -port_icon->get_size() * 0.5;
126
127
// Draw "shadow"/outline in the connection rim color.
128
draw_texture_rect(port_icon, Rect2(p_pos + (icon_offset - Size2(2, 2)) * EDSCALE, (port_icon->get_size() + Size2(4, 4)) * EDSCALE), false, p_rim_color);
129
draw_texture_rect(port_icon, Rect2(p_pos + icon_offset * EDSCALE, port_icon->get_size() * EDSCALE), false, p_color);
130
}
131
132
void VSGraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
133
Color rim_color = get_theme_color(SNAME("connection_rim_color"), SNAME("GraphEdit"));
134
_draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
135
}
136
137
///////////////////
138
139
void VSRerouteNode::_notification(int p_what) {
140
switch (p_what) {
141
case NOTIFICATION_READY: {
142
connect(SceneStringName(mouse_entered), callable_mp(this, &VSRerouteNode::_on_mouse_entered));
143
connect(SceneStringName(mouse_exited), callable_mp(this, &VSRerouteNode::_on_mouse_exited));
144
} break;
145
case NOTIFICATION_DRAW: {
146
Vector2 offset = Vector2(0, -16 * EDSCALE);
147
Color drag_bg_color = get_theme_color(SNAME("drag_background"), SNAME("VSRerouteNode"));
148
draw_circle(get_size() * 0.5 + offset, 16 * EDSCALE, Color(drag_bg_color, selected ? 1 : icon_opacity), true, -1, true);
149
150
Ref<Texture2D> icon = get_editor_theme_icon(SNAME("ToolMove"));
151
Point2 icon_offset = -icon->get_size() * 0.5 + get_size() * 0.5 + offset;
152
draw_texture(icon, icon_offset, Color(1, 1, 1, selected ? 1 : icon_opacity));
153
} break;
154
}
155
}
156
157
void VSRerouteNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
158
Color rim_color = selected ? get_theme_color("selected_rim_color", "VSRerouteNode") : get_theme_color("connection_rim_color", "GraphEdit");
159
_draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
160
}
161
162
VSRerouteNode::VSRerouteNode() {
163
Label *title_lbl = Object::cast_to<Label>(get_titlebar_hbox()->get_child(0));
164
title_lbl->hide();
165
166
const Size2 size = Size2(32, 32) * EDSCALE;
167
168
Control *slot_area = memnew(Control);
169
slot_area->set_custom_minimum_size(size);
170
slot_area->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
171
add_child(slot_area);
172
173
// Lay the input and output ports on top of each other to create the illusion of a single port.
174
add_theme_constant_override("port_h_offset", size.width / 2);
175
}
176
177
void VSRerouteNode::set_icon_opacity(float p_opacity) {
178
icon_opacity = p_opacity;
179
queue_redraw();
180
}
181
182
void VSRerouteNode::_on_mouse_entered() {
183
Ref<Tween> tween = create_tween();
184
tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 0.0, 1.0, FADE_ANIMATION_LENGTH_SEC);
185
}
186
187
void VSRerouteNode::_on_mouse_exited() {
188
Ref<Tween> tween = create_tween();
189
tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 1.0, 0.0, FADE_ANIMATION_LENGTH_SEC);
190
}
191
192
///////////////////
193
194
VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
195
vs_msdf_fonts_theme.instantiate();
196
}
197
198
void VisualShaderGraphPlugin::_bind_methods() {
199
ClassDB::bind_method("add_node", &VisualShaderGraphPlugin::add_node);
200
ClassDB::bind_method("remove_node", &VisualShaderGraphPlugin::remove_node);
201
ClassDB::bind_method("connect_nodes", &VisualShaderGraphPlugin::connect_nodes);
202
ClassDB::bind_method("disconnect_nodes", &VisualShaderGraphPlugin::disconnect_nodes);
203
ClassDB::bind_method("set_node_position", &VisualShaderGraphPlugin::set_node_position);
204
ClassDB::bind_method("update_node", &VisualShaderGraphPlugin::update_node);
205
ClassDB::bind_method("update_node_deferred", &VisualShaderGraphPlugin::update_node_deferred);
206
ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value);
207
ClassDB::bind_method("set_parameter_name", &VisualShaderGraphPlugin::set_parameter_name);
208
ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
209
ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
210
ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz);
211
ClassDB::bind_method(D_METHOD("attach_node_to_frame", "type", "id", "frame"), &VisualShaderGraphPlugin::attach_node_to_frame);
212
ClassDB::bind_method(D_METHOD("detach_node_from_frame", "type", "id"), &VisualShaderGraphPlugin::detach_node_from_frame);
213
ClassDB::bind_method(D_METHOD("set_frame_color_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_color_enabled);
214
ClassDB::bind_method(D_METHOD("set_frame_color", "type", "id", "color"), &VisualShaderGraphPlugin::set_frame_color);
215
ClassDB::bind_method(D_METHOD("set_frame_autoshrink_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_autoshrink_enabled);
216
}
217
218
void VisualShaderGraphPlugin::set_editor(VisualShaderEditor *p_editor) {
219
editor = p_editor;
220
}
221
222
void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) {
223
visual_shader = Ref<VisualShader>(p_shader);
224
}
225
226
void VisualShaderGraphPlugin::set_connections(const List<VisualShader::Connection> &p_connections) {
227
connections = p_connections;
228
}
229
230
void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id, bool p_is_valid) {
231
if (editor->get_current_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].output_ports.has(p_port_id)) {
232
Link &link = links[p_node_id];
233
234
for (const KeyValue<int, Port> &E : link.output_ports) {
235
if (E.value.preview_button != nullptr) {
236
E.value.preview_button->set_pressed(false);
237
}
238
}
239
bool is_dirty = link.preview_pos < 0;
240
241
if (!is_dirty && link.preview_visible && link.preview_box != nullptr) {
242
link.graph_element->remove_child(link.preview_box);
243
memdelete(link.preview_box);
244
link.preview_box = nullptr;
245
link.graph_element->reset_size();
246
link.preview_visible = false;
247
}
248
249
if (p_port_id != -1 && link.output_ports[p_port_id].preview_button != nullptr) {
250
if (is_dirty) {
251
link.preview_pos = link.graph_element->get_child_count();
252
}
253
254
VBoxContainer *vbox = memnew(VBoxContainer);
255
link.graph_element->add_child(vbox);
256
link.graph_element->move_child(vbox, link.preview_pos);
257
258
GraphNode *graph_node = Object::cast_to<GraphNode>(link.graph_element);
259
if (graph_node) {
260
graph_node->set_slot_draw_stylebox(vbox->get_index(false), false);
261
}
262
263
Control *offset = memnew(Control);
264
offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
265
vbox->add_child(offset);
266
267
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
268
port_preview->setup(visual_shader, editor->preview_material, editor->get_current_shader_type(), links[p_node_id].output_ports[p_port_id].type == VisualShaderNode::PORT_TYPE_VECTOR_4D, p_node_id, p_port_id, p_is_valid);
269
port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
270
vbox->add_child(port_preview);
271
link.preview_visible = true;
272
link.preview_box = vbox;
273
link.output_ports[p_port_id].preview_button->set_pressed(true);
274
}
275
}
276
}
277
278
void VisualShaderGraphPlugin::update_node_deferred(VisualShader::Type p_type, int p_node_id) {
279
callable_mp(this, &VisualShaderGraphPlugin::update_node).call_deferred(p_type, p_node_id);
280
}
281
282
void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_id) {
283
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id)) {
284
return;
285
}
286
remove_node(p_type, p_node_id, true);
287
add_node(p_type, p_node_id, true, true);
288
289
// TODO: Restore focus here?
290
}
291
292
void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, const Variant &p_value) {
293
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id)) {
294
return;
295
}
296
297
Button *button = links[p_node_id].input_ports[p_port_id].default_input_button;
298
299
switch (p_value.get_type()) {
300
case Variant::COLOR: {
301
button->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
302
303
Callable ce = callable_mp(editor, &VisualShaderEditor::_draw_color_over_button);
304
if (!button->is_connected(SceneStringName(draw), ce)) {
305
button->connect(SceneStringName(draw), ce.bind(button, p_value));
306
}
307
} break;
308
case Variant::BOOL: {
309
button->set_text(((bool)p_value) ? "true" : "false");
310
} break;
311
case Variant::INT:
312
case Variant::FLOAT: {
313
button->set_text(String::num(p_value, 4));
314
} break;
315
case Variant::VECTOR2: {
316
Vector2 v = p_value;
317
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3));
318
} break;
319
case Variant::VECTOR3: {
320
Vector3 v = p_value;
321
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3));
322
} break;
323
case Variant::VECTOR4: {
324
Vector4 v = p_value;
325
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3) + "," + String::num(v.w, 3));
326
} break;
327
default: {
328
}
329
}
330
}
331
332
void VisualShaderGraphPlugin::set_parameter_name(VisualShader::Type p_type, int p_node_id, const String &p_name) {
333
if (editor->get_current_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].parameter_name != nullptr) {
334
links[p_node_id].parameter_name->set_text(p_name);
335
}
336
}
337
338
void VisualShaderGraphPlugin::update_curve(int p_node_id) {
339
if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) {
340
Ref<VisualShaderNodeCurveTexture> tex = Object::cast_to<VisualShaderNodeCurveTexture>(links[p_node_id].visual_node);
341
ERR_FAIL_COND(tex.is_null());
342
343
if (tex->get_texture().is_valid()) {
344
links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve());
345
}
346
tex->emit_changed();
347
}
348
}
349
350
void VisualShaderGraphPlugin::update_curve_xyz(int p_node_id) {
351
if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) {
352
Ref<VisualShaderNodeCurveXYZTexture> tex = Object::cast_to<VisualShaderNodeCurveXYZTexture>(links[p_node_id].visual_node);
353
ERR_FAIL_COND(tex.is_null());
354
355
if (tex->get_texture().is_valid()) {
356
links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve_x());
357
links[p_node_id].curve_editors[1]->set_curve(tex->get_texture()->get_curve_y());
358
links[p_node_id].curve_editors[2]->set_curve(tex->get_texture()->get_curve_z());
359
}
360
tex->emit_changed();
361
}
362
}
363
364
int VisualShaderGraphPlugin::get_constant_index(float p_constant) const {
365
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
366
if (Math::is_equal_approx(p_constant, float_constant_defs[i].value)) {
367
return i + 1;
368
}
369
}
370
return 0;
371
}
372
373
void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression) {
374
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id) || !links[p_node_id].expression_edit) {
375
return;
376
}
377
links[p_node_id].expression_edit->set_text(p_expression);
378
}
379
380
void VisualShaderGraphPlugin::attach_node_to_frame(VisualShader::Type p_type, int p_node_id, int p_frame_id) {
381
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id) || !links.has(p_frame_id)) {
382
return;
383
}
384
385
GraphEdit *graph = editor->graph;
386
if (!graph) {
387
return;
388
}
389
390
// Get the hint label and hide it before attaching the node to prevent resizing issues with the frame.
391
GraphFrame *frame = Object::cast_to<GraphFrame>(links[p_frame_id].graph_element);
392
ERR_FAIL_COND_MSG(!frame, "VisualShader node to attach to is not a frame node.");
393
394
Label *frame_hint_label = Object::cast_to<Label>(frame->get_child(0, false));
395
if (frame_hint_label) {
396
frame_hint_label->hide();
397
}
398
399
graph->attach_graph_element_to_frame(itos(p_node_id), itos(p_frame_id));
400
}
401
402
void VisualShaderGraphPlugin::detach_node_from_frame(VisualShader::Type p_type, int p_node_id) {
403
GraphEdit *graph = editor->graph;
404
if (!graph) {
405
return;
406
}
407
408
const StringName node_name = itos(p_node_id);
409
GraphFrame *frame = graph->get_element_frame(node_name);
410
if (!frame) {
411
return;
412
}
413
414
graph->detach_graph_element_from_frame(node_name);
415
416
bool no_more_frames_attached = graph->get_attached_nodes_of_frame(frame->get_name()).is_empty();
417
418
if (no_more_frames_attached) {
419
// Get the hint label and show it.
420
Label *frame_hint_label = Object::cast_to<Label>(frame->get_child(0, false));
421
ERR_FAIL_COND_MSG(!frame_hint_label, "Frame node does not have a hint label.");
422
423
frame_hint_label->show();
424
}
425
}
426
427
void VisualShaderGraphPlugin::set_frame_color_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable) {
428
GraphEdit *graph = editor->graph;
429
ERR_FAIL_COND(!graph);
430
431
const NodePath node_name = itos(p_node_id);
432
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
433
if (!frame) {
434
return;
435
}
436
437
frame->set_tint_color_enabled(p_enable);
438
}
439
440
void VisualShaderGraphPlugin::set_frame_color(VisualShader::Type p_type, int p_node_id, const Color &p_color) {
441
GraphEdit *graph = editor->graph;
442
ERR_FAIL_COND(!graph);
443
444
const NodePath node_name = itos(p_node_id);
445
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
446
if (!frame) {
447
return;
448
}
449
450
frame->set_tint_color(p_color);
451
}
452
453
void VisualShaderGraphPlugin::set_frame_autoshrink_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable) {
454
GraphEdit *graph = editor->graph;
455
ERR_FAIL_COND(!graph);
456
457
const NodePath node_name = itos(p_node_id);
458
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
459
if (!frame) {
460
return;
461
}
462
463
frame->set_autoshrink_enabled(p_enable);
464
}
465
466
void VisualShaderGraphPlugin::update_reroute_nodes() {
467
for (const KeyValue<int, Link> &E : links) {
468
Ref<VisualShaderNodeReroute> reroute_node = Object::cast_to<VisualShaderNodeReroute>(E.value.visual_node);
469
if (reroute_node.is_valid()) {
470
update_node(editor->get_current_shader_type(), E.key);
471
}
472
}
473
}
474
475
Ref<Script> VisualShaderGraphPlugin::get_node_script(int p_node_id) const {
476
if (!links.has(p_node_id)) {
477
return Ref<Script>();
478
}
479
480
Ref<VisualShaderNodeCustom> custom = Ref<VisualShaderNodeCustom>(links[p_node_id].visual_node);
481
if (custom.is_valid()) {
482
return custom->get_script();
483
}
484
485
return Ref<Script>();
486
}
487
488
void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) {
489
links[p_node_id].input_ports.insert(p_port_id, { p_button });
490
}
491
492
void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *p_expression_edit) {
493
links[p_node_id].expression_edit = p_expression_edit;
494
}
495
496
void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor) {
497
links[p_node_id].curve_editors[p_index] = p_curve_editor;
498
}
499
500
void VisualShaderGraphPlugin::update_parameter_refs() {
501
for (KeyValue<int, Link> &E : links) {
502
VisualShaderNodeParameterRef *ref = Object::cast_to<VisualShaderNodeParameterRef>(E.value.visual_node);
503
if (ref) {
504
remove_node(E.value.type, E.key, true);
505
add_node(E.value.type, E.key, true, true);
506
}
507
}
508
}
509
510
// Only updates the linked frames of the given node, not the node itself (in case it's a frame node).
511
void VisualShaderGraphPlugin::update_frames(VisualShader::Type p_type, int p_node) {
512
GraphEdit *graph = editor->graph;
513
if (!graph) {
514
return;
515
}
516
517
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_node);
518
if (vsnode.is_null()) {
519
WARN_PRINT("Update linked frames: Node not found.");
520
return;
521
}
522
523
int frame_vsnode_id = vsnode->get_frame();
524
if (frame_vsnode_id == -1) {
525
return;
526
}
527
528
Ref<VisualShaderNodeFrame> frame_node = visual_shader->get_node(p_type, frame_vsnode_id);
529
if (frame_node.is_null() || !links.has(frame_vsnode_id)) {
530
return;
531
}
532
533
GraphFrame *frame = Object::cast_to<GraphFrame>(links[frame_vsnode_id].graph_element);
534
if (!frame) {
535
return;
536
}
537
538
// Update the frame node recursively.
539
editor->graph->_update_graph_frame(frame);
540
}
541
542
void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) {
543
if (editor->get_current_shader_type() == p_type && links.has(p_id)) {
544
links[p_id].graph_element->set_position_offset(p_position * editor->cached_theme_base_scale);
545
}
546
}
547
548
bool VisualShaderGraphPlugin::is_preview_visible(int p_id) const {
549
return links[p_id].preview_visible;
550
}
551
552
void VisualShaderGraphPlugin::clear_links() {
553
links.clear();
554
}
555
556
void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphElement *p_graph_element) {
557
links.insert(p_id, { p_type, p_visual_node, p_graph_element, p_visual_node->get_output_port_for_preview() != -1, -1, HashMap<int, InputPort>(), HashMap<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } });
558
}
559
560
void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, VisualShaderNode::PortType p_port_type, TextureButton *p_button) {
561
links[p_node_id].output_ports.insert(p_port, { p_port_type, p_button });
562
}
563
564
void VisualShaderGraphPlugin::register_parameter_name(int p_node_id, LineEdit *p_parameter_name) {
565
links[p_node_id].parameter_name = p_parameter_name;
566
}
567
568
void VisualShaderGraphPlugin::update_theme() {
569
vector_expanded_color[0] = editor->get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)); // red
570
vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)); // green
571
vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), EditorStringName(Editor)); // blue
572
vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), EditorStringName(Editor)); // alpha
573
574
Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts));
575
Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts));
576
vs_msdf_fonts_theme->set_font(SceneStringName(font), "Label", label_font);
577
vs_msdf_fonts_theme->set_font(SceneStringName(font), "GraphNodeTitleLabel", label_bold_font);
578
if (!EditorThemeManager::is_dark_icon_and_font()) {
579
// Override the color to white for light themes.
580
vs_msdf_fonts_theme->set_color(SceneStringName(font_color), "GraphNodeTitleLabel", Color(1, 1, 1));
581
}
582
vs_msdf_fonts_theme->set_font(SceneStringName(font), "LineEdit", label_font);
583
vs_msdf_fonts_theme->set_font(SceneStringName(font), "Button", label_font);
584
}
585
586
bool VisualShaderGraphPlugin::is_node_has_parameter_instances_relatively(VisualShader::Type p_type, int p_node) const {
587
bool result = false;
588
589
Ref<VisualShaderNodeParameter> parameter_node = Object::cast_to<VisualShaderNodeParameter>(visual_shader->get_node_unchecked(p_type, p_node).ptr());
590
if (parameter_node.is_valid()) {
591
if (parameter_node->get_qualifier() == VisualShaderNodeParameter::QUAL_INSTANCE) {
592
return true;
593
}
594
}
595
596
const LocalVector<int> &prev_connected_nodes = visual_shader->get_prev_connected_nodes(p_type, p_node);
597
598
for (const int &E : prev_connected_nodes) {
599
result = is_node_has_parameter_instances_relatively(p_type, E);
600
if (result) {
601
break;
602
}
603
}
604
605
return result;
606
}
607
608
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool p_just_update, bool p_update_frames) {
609
if (visual_shader.is_null() || p_type != editor->get_current_shader_type()) {
610
return;
611
}
612
GraphEdit *graph = editor->graph;
613
if (!graph) {
614
return;
615
}
616
VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
617
if (!graph_plugin) {
618
return;
619
}
620
Shader::Mode mode = visual_shader->get_mode();
621
622
Control *offset;
623
624
const Color type_color[] = {
625
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
626
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
627
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
628
EDITOR_GET("editors/visual_editors/connection_colors/vector2_color"),
629
EDITOR_GET("editors/visual_editors/connection_colors/vector3_color"),
630
EDITOR_GET("editors/visual_editors/connection_colors/vector4_color"),
631
EDITOR_GET("editors/visual_editors/connection_colors/boolean_color"),
632
EDITOR_GET("editors/visual_editors/connection_colors/transform_color"),
633
EDITOR_GET("editors/visual_editors/connection_colors/sampler_color"),
634
};
635
636
// Keep in sync with VisualShaderNode::Category.
637
const Color category_color[VisualShaderNode::Category::CATEGORY_MAX] = {
638
Color(0.0, 0.0, 0.0), // None (default, not used)
639
EDITOR_GET("editors/visual_editors/category_colors/output_color"),
640
EDITOR_GET("editors/visual_editors/category_colors/color_color"),
641
EDITOR_GET("editors/visual_editors/category_colors/conditional_color"),
642
EDITOR_GET("editors/visual_editors/category_colors/input_color"),
643
EDITOR_GET("editors/visual_editors/category_colors/scalar_color"),
644
EDITOR_GET("editors/visual_editors/category_colors/textures_color"),
645
EDITOR_GET("editors/visual_editors/category_colors/transform_color"),
646
EDITOR_GET("editors/visual_editors/category_colors/utility_color"),
647
EDITOR_GET("editors/visual_editors/category_colors/vector_color"),
648
EDITOR_GET("editors/visual_editors/category_colors/special_color"),
649
EDITOR_GET("editors/visual_editors/category_colors/particle_color"),
650
};
651
652
static const String vector_expanded_name[4] = { "red", "green", "blue", "alpha" };
653
654
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
655
ERR_FAIL_COND(vsnode.is_null());
656
657
Ref<VisualShaderNodeResizableBase> resizable_node = vsnode;
658
bool is_resizable = resizable_node.is_valid();
659
Size2 size = Size2(0, 0);
660
661
Ref<VisualShaderNodeGroupBase> group_node = vsnode;
662
bool is_group = group_node.is_valid();
663
664
Ref<VisualShaderNodeFrame> frame_node = vsnode;
665
bool is_frame = frame_node.is_valid();
666
667
Ref<VisualShaderNodeExpression> expression_node = group_node;
668
bool is_expression = expression_node.is_valid();
669
String expression = "";
670
671
Ref<VisualShaderNodeReroute> reroute_node = vsnode;
672
bool is_reroute = reroute_node.is_valid();
673
674
Ref<VisualShaderNodeCustom> custom_node = vsnode;
675
if (custom_node.is_valid()) {
676
custom_node->_set_initialized(true);
677
}
678
679
GraphElement *node;
680
if (is_frame) {
681
GraphFrame *frame = memnew(GraphFrame);
682
frame->set_title(vsnode->get_caption());
683
node = frame;
684
} else if (is_reroute) {
685
VSRerouteNode *reroute_gnode = memnew(VSRerouteNode);
686
reroute_gnode->set_ignore_invalid_connection_type(true);
687
node = reroute_gnode;
688
} else {
689
VSGraphNode *gnode = memnew(VSGraphNode);
690
gnode->set_title(vsnode->get_caption());
691
node = gnode;
692
}
693
node->set_name(itos(p_id));
694
695
// All nodes are closable except the output node.
696
if (p_id >= 2) {
697
vsnode->set_deletable(true);
698
node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED);
699
}
700
graph->add_child(node);
701
node->set_theme(vs_msdf_fonts_theme);
702
703
// Set the node's titlebar color based on its category.
704
if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE && !is_frame && !is_reroute) {
705
Ref<StyleBoxFlat> sb_colored = editor->get_theme_stylebox("titlebar", "GraphNode")->duplicate();
706
sb_colored->set_bg_color(category_color[vsnode->get_category()]);
707
node->add_theme_style_override("titlebar", sb_colored);
708
709
Ref<StyleBoxFlat> sb_colored_selected = editor->get_theme_stylebox("titlebar_selected", "GraphNode")->duplicate();
710
sb_colored_selected->set_bg_color(category_color[vsnode->get_category()].lightened(0.2));
711
node->add_theme_style_override("titlebar_selected", sb_colored_selected);
712
}
713
714
if (p_just_update) {
715
Link &link = links[p_id];
716
717
link.visual_node = vsnode.ptr();
718
link.graph_element = node;
719
link.preview_box = nullptr;
720
link.preview_pos = -1;
721
link.output_ports.clear();
722
link.input_ports.clear();
723
} else {
724
register_link(p_type, p_id, vsnode.ptr(), node);
725
}
726
727
if (is_resizable) {
728
size = resizable_node->get_size();
729
730
node->set_resizable(true);
731
node->connect("resize_end", callable_mp(editor, &VisualShaderEditor::_node_resized).bind((int)p_type, p_id));
732
node->set_size(size);
733
// node->call_deferred(SNAME("set_size"), size);
734
// editor->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size);
735
}
736
737
if (is_expression) {
738
expression = expression_node->get_expression();
739
}
740
741
node->set_position_offset(visual_shader->get_node_position(p_type, p_id) * editor->cached_theme_base_scale);
742
743
node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged).bind(p_id));
744
745
Control *custom_editor = nullptr;
746
int port_offset = 1;
747
748
if (p_update_frames) {
749
if (vsnode->get_frame() > -1) {
750
graph->attach_graph_element_to_frame(itos(p_id), itos(vsnode->get_frame()));
751
} else {
752
graph->detach_graph_element_from_frame(itos(p_id));
753
}
754
}
755
756
if (is_frame) {
757
GraphFrame *graph_frame = Object::cast_to<GraphFrame>(node);
758
ERR_FAIL_NULL(graph_frame);
759
760
graph_frame->set_tint_color_enabled(frame_node->is_tint_color_enabled());
761
graph_frame->set_tint_color(frame_node->get_tint_color());
762
763
// Add hint label.
764
Label *frame_hint_label = memnew(Label);
765
frame_hint_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
766
node->add_child(frame_hint_label);
767
frame_hint_label->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER);
768
frame_hint_label->set_vertical_alignment(VerticalAlignment::VERTICAL_ALIGNMENT_CENTER);
769
frame_hint_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
770
frame_hint_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
771
frame_hint_label->set_text(TTR("Drag and drop nodes here to attach them."));
772
frame_hint_label->set_modulate(Color(1.0, 1.0, 1.0, 0.3));
773
graph_frame->set_autoshrink_enabled(frame_node->is_autoshrink_enabled());
774
775
if (frame_node->get_attached_nodes().is_empty()) {
776
frame_hint_label->show();
777
} else {
778
frame_hint_label->hide();
779
}
780
781
// Attach all nodes.
782
if (p_update_frames && frame_node->get_attached_nodes().size() > 0) {
783
for (const int &id : frame_node->get_attached_nodes()) {
784
graph->attach_graph_element_to_frame(itos(id), node->get_name());
785
}
786
}
787
788
// We should be done here.
789
return;
790
}
791
792
if (!is_reroute) {
793
Control *content_offset = memnew(Control);
794
content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
795
node->add_child(content_offset);
796
}
797
798
if (is_group) {
799
port_offset += 1;
800
}
801
802
// Set the minimum width of a node based on the preview size to avoid a resize when toggling the preview.
803
Ref<StyleBoxFlat> graph_node_stylebox = graph->get_theme_stylebox(SceneStringName(panel), "GraphNode");
804
int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
805
if (!is_frame && !is_reroute) {
806
node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0));
807
}
808
809
Ref<VisualShaderNodeParticleEmit> emit = vsnode;
810
if (emit.is_valid()) {
811
node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
812
}
813
814
Ref<VisualShaderNodeParameterRef> parameter_ref = vsnode;
815
if (parameter_ref.is_valid()) {
816
parameter_ref->set_shader_rid(visual_shader->get_rid());
817
parameter_ref->update_parameter_type();
818
}
819
820
Ref<VisualShaderNodeVarying> varying = vsnode;
821
if (varying.is_valid()) {
822
varying->set_shader_rid(visual_shader->get_rid());
823
}
824
825
Ref<VisualShaderNodeParameter> parameter = vsnode;
826
HBoxContainer *hb = nullptr;
827
828
if (parameter.is_valid()) {
829
LineEdit *parameter_name = memnew(LineEdit);
830
register_parameter_name(p_id, parameter_name);
831
parameter_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
832
parameter_name->set_text(parameter->get_parameter_name());
833
parameter_name->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_parameter_line_edit_changed).bind(p_id));
834
parameter_name->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_parameter_line_edit_focus_out).bind(parameter_name, p_id));
835
836
if (vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
837
hb = memnew(HBoxContainer);
838
hb->add_child(parameter_name);
839
node->add_child(hb);
840
} else {
841
node->add_child(parameter_name);
842
}
843
port_offset++;
844
}
845
846
for (int i = 0; i < editor->plugins.size(); i++) {
847
vsnode->set_meta("id", p_id);
848
vsnode->set_meta("shader_type", (int)p_type);
849
custom_editor = editor->plugins.write[i]->create_editor(visual_shader, vsnode);
850
vsnode->remove_meta("id");
851
vsnode->remove_meta("shader_type");
852
if (custom_editor) {
853
if (vsnode->is_show_prop_names()) {
854
custom_editor->call_deferred(SNAME("_show_prop_names"), true);
855
}
856
break;
857
}
858
}
859
860
if (custom_node.is_valid()) {
861
bool first = true;
862
VBoxContainer *vbox = nullptr;
863
864
int i = 0;
865
for (List<VisualShaderNodeCustom::DropDownListProperty>::ConstIterator itr = custom_node->dp_props.begin(); itr != custom_node->dp_props.end(); ++itr, ++i) {
866
const VisualShaderNodeCustom::DropDownListProperty &dp = *itr;
867
868
if (first) {
869
first = false;
870
vbox = memnew(VBoxContainer);
871
node->add_child(vbox);
872
port_offset++;
873
}
874
875
HBoxContainer *hbox = memnew(HBoxContainer);
876
vbox->add_child(hbox);
877
hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
878
879
String prop_name = dp.name.strip_edges();
880
if (!prop_name.is_empty()) {
881
Label *label = memnew(Label);
882
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
883
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
884
label->set_text(prop_name + ":");
885
hbox->add_child(label);
886
}
887
888
OptionButton *op = memnew(OptionButton);
889
hbox->add_child(op);
890
op->set_h_size_flags(Control::SIZE_EXPAND_FILL);
891
op->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_set_custom_node_option).bind(p_id, i), CONNECT_DEFERRED);
892
893
for (const String &s : dp.options) {
894
op->add_item(s);
895
}
896
if (custom_node->dp_selected_cache.has(i)) {
897
op->select(custom_node->dp_selected_cache[i]);
898
} else {
899
op->select(0);
900
}
901
}
902
}
903
904
Ref<VisualShaderNodeCurveTexture> curve = vsnode;
905
Ref<VisualShaderNodeCurveXYZTexture> curve_xyz = vsnode;
906
907
bool is_curve = curve.is_valid() || curve_xyz.is_valid();
908
if (is_curve) {
909
hb = memnew(HBoxContainer);
910
node->add_child(hb);
911
}
912
913
if (curve.is_valid()) {
914
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
915
916
if (curve->get_texture().is_valid()) {
917
curve->get_texture()->connect_changed(callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve).bind(p_id));
918
}
919
920
CurveEditor *curve_editor = memnew(CurveEditor);
921
node->add_child(curve_editor);
922
register_curve_editor(p_id, 0, curve_editor);
923
curve_editor->set_custom_minimum_size(Size2(300, 0));
924
curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
925
if (curve->get_texture().is_valid()) {
926
curve_editor->set_curve(curve->get_texture()->get_curve());
927
}
928
}
929
930
if (curve_xyz.is_valid()) {
931
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
932
933
if (curve_xyz->get_texture().is_valid()) {
934
curve_xyz->get_texture()->connect_changed(callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve_xyz).bind(p_id));
935
}
936
937
CurveEditor *curve_editor_x = memnew(CurveEditor);
938
node->add_child(curve_editor_x);
939
register_curve_editor(p_id, 0, curve_editor_x);
940
curve_editor_x->set_custom_minimum_size(Size2(300, 0));
941
curve_editor_x->set_h_size_flags(Control::SIZE_EXPAND_FILL);
942
if (curve_xyz->get_texture().is_valid()) {
943
curve_editor_x->set_curve(curve_xyz->get_texture()->get_curve_x());
944
}
945
946
CurveEditor *curve_editor_y = memnew(CurveEditor);
947
node->add_child(curve_editor_y);
948
register_curve_editor(p_id, 1, curve_editor_y);
949
curve_editor_y->set_custom_minimum_size(Size2(300, 0));
950
curve_editor_y->set_h_size_flags(Control::SIZE_EXPAND_FILL);
951
if (curve_xyz->get_texture().is_valid()) {
952
curve_editor_y->set_curve(curve_xyz->get_texture()->get_curve_y());
953
}
954
955
CurveEditor *curve_editor_z = memnew(CurveEditor);
956
node->add_child(curve_editor_z);
957
register_curve_editor(p_id, 2, curve_editor_z);
958
curve_editor_z->set_custom_minimum_size(Size2(300, 0));
959
curve_editor_z->set_h_size_flags(Control::SIZE_EXPAND_FILL);
960
if (curve_xyz->get_texture().is_valid()) {
961
curve_editor_z->set_curve(curve_xyz->get_texture()->get_curve_z());
962
}
963
}
964
965
if (custom_editor) {
966
if (is_curve || (hb == nullptr && !vsnode->is_use_prop_slots() && (vsnode->get_output_port_count() == 0 || vsnode->get_output_port_name(0) == "") && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == ""))) {
967
// Will be embedded in first port.
968
} else {
969
port_offset++;
970
node->add_child(custom_editor);
971
custom_editor = nullptr;
972
}
973
}
974
975
if (is_group) {
976
if (group_node->is_editable()) {
977
HBoxContainer *hb2 = memnew(HBoxContainer);
978
979
String input_port_name = "input" + itos(group_node->get_free_input_port_id());
980
String output_port_name = "output" + itos(group_node->get_free_output_port_id());
981
982
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
983
if (i < vsnode->get_input_port_count()) {
984
if (input_port_name == vsnode->get_input_port_name(i)) {
985
input_port_name = "_" + input_port_name;
986
}
987
}
988
if (i < vsnode->get_output_port_count()) {
989
if (output_port_name == vsnode->get_output_port_name(i)) {
990
output_port_name = "_" + output_port_name;
991
}
992
}
993
}
994
995
Button *add_input_btn = memnew(Button);
996
add_input_btn->set_text(TTR("Add Input"));
997
add_input_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_add_input_port).bind(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, input_port_name), CONNECT_DEFERRED);
998
hb2->add_child(add_input_btn);
999
1000
hb2->add_spacer();
1001
1002
Button *add_output_btn = memnew(Button);
1003
add_output_btn->set_text(TTR("Add Output"));
1004
add_output_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_add_output_port).bind(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR_3D, output_port_name), CONNECT_DEFERRED);
1005
hb2->add_child(add_output_btn);
1006
1007
node->add_child(hb2);
1008
}
1009
}
1010
1011
int output_port_count = 0;
1012
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
1013
if (vsnode->_is_output_port_expanded(i)) {
1014
switch (vsnode->get_output_port_type(i)) {
1015
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1016
output_port_count += 2;
1017
} break;
1018
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1019
output_port_count += 3;
1020
} break;
1021
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1022
output_port_count += 4;
1023
} break;
1024
default:
1025
break;
1026
}
1027
}
1028
output_port_count++;
1029
}
1030
int max_ports = MAX(vsnode->get_input_port_count(), output_port_count);
1031
VisualShaderNode::PortType expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1032
int expanded_port_counter = 0;
1033
1034
for (int i = 0, j = 0; i < max_ports; i++, j++) {
1035
switch (expanded_type) {
1036
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1037
if (expanded_port_counter >= 2) {
1038
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1039
expanded_port_counter = 0;
1040
i -= 2;
1041
}
1042
} break;
1043
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1044
if (expanded_port_counter >= 3) {
1045
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1046
expanded_port_counter = 0;
1047
i -= 3;
1048
}
1049
} break;
1050
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1051
if (expanded_port_counter >= 4) {
1052
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1053
expanded_port_counter = 0;
1054
i -= 4;
1055
}
1056
} break;
1057
default:
1058
break;
1059
}
1060
1061
if (vsnode->is_port_separator(i)) {
1062
HSeparator *separator = memnew(HSeparator);
1063
separator->add_theme_style_override("separator", editor->get_theme_stylebox("separator", "GraphNode"));
1064
node->add_child(separator);
1065
port_offset++;
1066
}
1067
1068
bool valid_left = j < vsnode->get_input_port_count();
1069
VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1070
bool port_left_used = false;
1071
String name_left;
1072
if (valid_left) {
1073
name_left = vsnode->get_input_port_name(j);
1074
port_left = vsnode->get_input_port_type(j);
1075
for (const VisualShader::Connection &E : connections) {
1076
if (E.to_node == p_id && E.to_port == j) {
1077
port_left_used = true;
1078
break;
1079
}
1080
}
1081
}
1082
1083
bool valid_right = true;
1084
VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR;
1085
String name_right;
1086
1087
if (expanded_type == VisualShaderNode::PORT_TYPE_SCALAR) {
1088
valid_right = i < vsnode->get_output_port_count();
1089
if (valid_right) {
1090
name_right = vsnode->get_output_port_name(i);
1091
port_right = vsnode->get_output_port_type(i);
1092
}
1093
} else {
1094
name_right = vector_expanded_name[expanded_port_counter++];
1095
}
1096
1097
bool is_first_hbox = false;
1098
if (i == 0 && hb != nullptr) {
1099
is_first_hbox = true;
1100
} else {
1101
hb = memnew(HBoxContainer);
1102
}
1103
hb->add_theme_constant_override("separation", 7 * EDSCALE);
1104
1105
// Default value button/property editor.
1106
Variant default_value;
1107
1108
if (valid_left && !port_left_used) {
1109
default_value = vsnode->get_input_port_default_value(j);
1110
}
1111
1112
Button *default_input_btn = memnew(Button);
1113
hb->add_child(default_input_btn);
1114
register_default_input_button(p_id, j, default_input_btn);
1115
default_input_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(default_input_btn, p_id, j));
1116
if (default_value.get_type() != Variant::NIL) { // only a label
1117
set_input_port_default_value(p_type, p_id, j, default_value);
1118
} else {
1119
default_input_btn->hide();
1120
}
1121
1122
if (j == 0 && custom_editor) {
1123
hb->add_child(custom_editor);
1124
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1125
} else {
1126
if (valid_left) {
1127
if (is_group) {
1128
OptionButton *type_box = memnew(OptionButton);
1129
hb->add_child(type_box);
1130
type_box->add_item(TTR("Float"));
1131
type_box->add_item(TTR("Int"));
1132
type_box->add_item(TTR("UInt"));
1133
type_box->add_item(TTR("Vector2"));
1134
type_box->add_item(TTR("Vector3"));
1135
type_box->add_item(TTR("Vector4"));
1136
type_box->add_item(TTR("Boolean"));
1137
type_box->add_item(TTR("Transform"));
1138
type_box->add_item(TTR("Sampler"));
1139
type_box->select(group_node->get_input_port_type(j));
1140
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
1141
type_box->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_change_input_port_type).bind(p_id, j), CONNECT_DEFERRED);
1142
1143
LineEdit *name_box = memnew(LineEdit);
1144
hb->add_child(name_box);
1145
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
1146
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1147
name_box->set_text(name_left);
1148
name_box->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_change_input_port_name).bind(name_box, p_id, j), CONNECT_DEFERRED);
1149
name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, j, false), CONNECT_DEFERRED);
1150
1151
Button *remove_btn = memnew(Button);
1152
remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
1153
remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left);
1154
remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, j), CONNECT_DEFERRED);
1155
hb->add_child(remove_btn);
1156
} else {
1157
Label *label = memnew(Label);
1158
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1159
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
1160
label->set_text(name_left);
1161
label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
1162
hb->add_child(label);
1163
1164
if (vsnode->is_input_port_default(j, mode) && !port_left_used) {
1165
Label *hint_label = memnew(Label);
1166
hint_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1167
hint_label->set_text(TTR("[default]"));
1168
hint_label->add_theme_color_override(SceneStringName(font_color), editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit")));
1169
hint_label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
1170
hb->add_child(hint_label);
1171
}
1172
}
1173
}
1174
1175
if (!is_group && !is_first_hbox) {
1176
hb->add_spacer();
1177
}
1178
1179
if (valid_right) {
1180
if (is_group) {
1181
Button *remove_btn = memnew(Button);
1182
remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
1183
remove_btn->set_tooltip_text(TTR("Remove") + " " + name_right);
1184
remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED);
1185
hb->add_child(remove_btn);
1186
1187
LineEdit *name_box = memnew(LineEdit);
1188
hb->add_child(name_box);
1189
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
1190
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1191
name_box->set_text(name_right);
1192
name_box->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_change_output_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED);
1193
name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, true), CONNECT_DEFERRED);
1194
1195
OptionButton *type_box = memnew(OptionButton);
1196
hb->add_child(type_box);
1197
type_box->add_item(TTR("Float"));
1198
type_box->add_item(TTR("Int"));
1199
type_box->add_item(TTR("UInt"));
1200
type_box->add_item(TTR("Vector2"));
1201
type_box->add_item(TTR("Vector3"));
1202
type_box->add_item(TTR("Vector4"));
1203
type_box->add_item(TTR("Boolean"));
1204
type_box->add_item(TTR("Transform"));
1205
type_box->select(group_node->get_output_port_type(i));
1206
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
1207
type_box->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_change_output_port_type).bind(p_id, i), CONNECT_DEFERRED);
1208
} else {
1209
Label *label = memnew(Label);
1210
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1211
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
1212
label->set_text(name_right);
1213
label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact
1214
hb->add_child(label);
1215
}
1216
}
1217
}
1218
1219
if (valid_right) {
1220
if (expanded_port_counter == 0 && vsnode->is_output_port_expandable(i)) {
1221
TextureButton *expand = memnew(TextureButton);
1222
expand->set_accessibility_name(TTRC("Expand output port"));
1223
expand->set_toggle_mode(true);
1224
expand->set_texture_normal(editor->get_editor_theme_icon(SNAME("GuiTreeArrowRight")));
1225
expand->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiTreeArrowDown")));
1226
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
1227
expand->set_pressed(vsnode->_is_output_port_expanded(i));
1228
expand->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_expand_output_port).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
1229
hb->add_child(expand);
1230
}
1231
if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
1232
TextureButton *preview = memnew(TextureButton);
1233
preview->set_accessibility_name(TTRC("Select preview port"));
1234
preview->set_toggle_mode(true);
1235
preview->set_texture_normal(editor->get_editor_theme_icon(SNAME("GuiVisibilityHidden")));
1236
preview->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiVisibilityVisible")));
1237
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
1238
1239
register_output_port(p_id, j, port_right, preview);
1240
1241
preview->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED);
1242
hb->add_child(preview);
1243
}
1244
}
1245
1246
if (is_group) {
1247
offset = memnew(Control);
1248
offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
1249
node->add_child(offset);
1250
port_offset++;
1251
}
1252
1253
if (!is_first_hbox && !is_reroute) {
1254
node->add_child(hb);
1255
if (curve_xyz.is_valid()) {
1256
node->move_child(hb, 1 + expanded_port_counter);
1257
}
1258
}
1259
1260
if (expanded_type != VisualShaderNode::PORT_TYPE_SCALAR) {
1261
continue;
1262
}
1263
1264
int idx = is_first_hbox ? 1 : i + port_offset;
1265
if (is_reroute) {
1266
idx = 0;
1267
}
1268
if (!is_frame) {
1269
GraphNode *graph_node = Object::cast_to<GraphNode>(node);
1270
1271
graph_node->set_slot(idx, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
1272
1273
if (vsnode->_is_output_port_expanded(i)) {
1274
switch (vsnode->get_output_port_type(i)) {
1275
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1276
port_offset++;
1277
valid_left = (i + 1) < vsnode->get_input_port_count();
1278
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1279
if (valid_left) {
1280
port_left = vsnode->get_input_port_type(i + 1);
1281
}
1282
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1283
port_offset++;
1284
1285
valid_left = (i + 2) < vsnode->get_input_port_count();
1286
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1287
if (valid_left) {
1288
port_left = vsnode->get_input_port_type(i + 2);
1289
}
1290
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1291
1292
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_2D;
1293
} break;
1294
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1295
port_offset++;
1296
valid_left = (i + 1) < vsnode->get_input_port_count();
1297
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1298
if (valid_left) {
1299
port_left = vsnode->get_input_port_type(i + 1);
1300
}
1301
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1302
port_offset++;
1303
1304
valid_left = (i + 2) < vsnode->get_input_port_count();
1305
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1306
if (valid_left) {
1307
port_left = vsnode->get_input_port_type(i + 2);
1308
}
1309
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1310
port_offset++;
1311
1312
valid_left = (i + 3) < vsnode->get_input_port_count();
1313
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1314
if (valid_left) {
1315
port_left = vsnode->get_input_port_type(i + 3);
1316
}
1317
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
1318
1319
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_3D;
1320
} break;
1321
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1322
port_offset++;
1323
valid_left = (i + 1) < vsnode->get_input_port_count();
1324
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1325
if (valid_left) {
1326
port_left = vsnode->get_input_port_type(i + 1);
1327
}
1328
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1329
port_offset++;
1330
1331
valid_left = (i + 2) < vsnode->get_input_port_count();
1332
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1333
if (valid_left) {
1334
port_left = vsnode->get_input_port_type(i + 2);
1335
}
1336
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1337
port_offset++;
1338
1339
valid_left = (i + 3) < vsnode->get_input_port_count();
1340
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1341
if (valid_left) {
1342
port_left = vsnode->get_input_port_type(i + 3);
1343
}
1344
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
1345
port_offset++;
1346
1347
valid_left = (i + 4) < vsnode->get_input_port_count();
1348
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1349
if (valid_left) {
1350
port_left = vsnode->get_input_port_type(i + 4);
1351
}
1352
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[3]);
1353
1354
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_4D;
1355
} break;
1356
default:
1357
break;
1358
}
1359
}
1360
}
1361
}
1362
1363
bool has_relative_parameter_instances = false;
1364
if (vsnode->get_output_port_for_preview() >= 0) {
1365
has_relative_parameter_instances = is_node_has_parameter_instances_relatively(p_type, p_id);
1366
show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview(), !has_relative_parameter_instances);
1367
} else if (!is_reroute) {
1368
offset = memnew(Control);
1369
offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE));
1370
node->add_child(offset);
1371
}
1372
1373
String error = vsnode->get_warning(mode, p_type);
1374
if (has_relative_parameter_instances) {
1375
error += "\n" + TTR("The 2D preview cannot correctly show the result retrieved from instance parameter.");
1376
}
1377
if (!error.is_empty()) {
1378
Label *error_label = memnew(Label);
1379
error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1380
error_label->add_theme_color_override(SceneStringName(font_color), editor->get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
1381
error_label->set_text(error);
1382
error_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
1383
node->add_child(error_label);
1384
}
1385
1386
if (is_expression) {
1387
CodeEdit *expression_box = memnew(CodeEdit);
1388
Ref<CodeHighlighter> expression_syntax_highlighter;
1389
expression_syntax_highlighter.instantiate();
1390
expression_node->set_ctrl_pressed(expression_box, 0);
1391
expression_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
1392
node->add_child(expression_box);
1393
1394
Control *offset2 = memnew(Control);
1395
offset2->set_custom_minimum_size(Vector2(0, 11 * EDSCALE));
1396
node->add_child(offset2);
1397
1398
register_expression_edit(p_id, expression_box);
1399
1400
Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
1401
Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
1402
Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
1403
Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
1404
Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
1405
Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
1406
Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
1407
Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
1408
1409
expression_box->set_syntax_highlighter(expression_syntax_highlighter);
1410
1411
for (const String &E : editor->keyword_list) {
1412
if (ShaderLanguage::is_control_flow_keyword(E)) {
1413
expression_syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
1414
} else {
1415
expression_syntax_highlighter->add_keyword_color(E, keyword_color);
1416
}
1417
}
1418
1419
expression_box->begin_bulk_theme_override();
1420
expression_box->add_theme_font_override(SceneStringName(font), editor->get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)));
1421
expression_box->add_theme_font_size_override(SceneStringName(font_size), editor->get_theme_font_size(SNAME("expression_size"), EditorStringName(EditorFonts)));
1422
expression_box->add_theme_color_override(SceneStringName(font_color), text_color);
1423
expression_box->end_bulk_theme_override();
1424
1425
expression_syntax_highlighter->set_number_color(number_color);
1426
expression_syntax_highlighter->set_symbol_color(symbol_color);
1427
expression_syntax_highlighter->set_function_color(function_color);
1428
expression_syntax_highlighter->set_member_variable_color(members_color);
1429
expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
1430
expression_syntax_highlighter->add_color_region("//", "", comment_color, true);
1431
1432
expression_box->clear_comment_delimiters();
1433
expression_box->add_comment_delimiter("/*", "*/", false);
1434
expression_box->add_comment_delimiter("//", "", true);
1435
1436
if (!expression_box->has_auto_brace_completion_open_key("/*")) {
1437
expression_box->add_auto_brace_completion_pair("/*", "*/");
1438
}
1439
1440
expression_box->set_text(expression);
1441
expression_box->set_context_menu_enabled(false);
1442
expression_box->set_draw_line_numbers(true);
1443
1444
expression_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_expression_focus_out).bind(expression_box, p_id));
1445
}
1446
}
1447
1448
void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id, bool p_just_update) {
1449
if (editor->get_current_shader_type() == p_type && links.has(p_id)) {
1450
GraphEdit *graph_edit = editor->graph;
1451
if (!graph_edit) {
1452
return;
1453
}
1454
1455
graph_edit->remove_child(links[p_id].graph_element);
1456
memdelete(links[p_id].graph_element);
1457
if (!p_just_update) {
1458
links.erase(p_id);
1459
}
1460
}
1461
}
1462
1463
void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1464
GraphEdit *graph = editor->graph;
1465
if (!graph) {
1466
return;
1467
}
1468
1469
if (visual_shader.is_valid() && editor->get_current_shader_type() == p_type) {
1470
// Update reroute nodes since their port type might have changed.
1471
Ref<VisualShaderNodeReroute> reroute_to = visual_shader->get_node(p_type, p_to_node);
1472
Ref<VisualShaderNodeReroute> reroute_from = visual_shader->get_node(p_type, p_from_node);
1473
if (reroute_to.is_valid() || reroute_from.is_valid()) {
1474
update_reroute_nodes();
1475
}
1476
1477
graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
1478
1479
connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port });
1480
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) {
1481
links[p_to_node].input_ports[p_to_port].default_input_button->hide();
1482
}
1483
}
1484
}
1485
1486
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1487
GraphEdit *graph = editor->graph;
1488
if (!graph) {
1489
return;
1490
}
1491
1492
if (visual_shader.is_valid() && editor->get_current_shader_type() == p_type) {
1493
graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
1494
1495
for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
1496
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) {
1497
connections.erase(E);
1498
break;
1499
}
1500
}
1501
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) {
1502
links[p_to_node].input_ports[p_to_port].default_input_button->show();
1503
set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port));
1504
}
1505
}
1506
}
1507
1508
/////////////////
1509
1510
void VisualShaderEditedProperty::_bind_methods() {
1511
ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualShaderEditedProperty::set_edited_property);
1512
ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualShaderEditedProperty::get_edited_property);
1513
1514
ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property");
1515
}
1516
1517
void VisualShaderEditedProperty::set_edited_property(const Variant &p_variant) {
1518
edited_property = p_variant;
1519
}
1520
1521
Variant VisualShaderEditedProperty::get_edited_property() const {
1522
return edited_property;
1523
}
1524
1525
/////////////////
1526
1527
Vector2 VisualShaderEditor::selection_center;
1528
List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer;
1529
List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer;
1530
1531
void VisualShaderEditor::edit_shader(const Ref<Shader> &p_shader) {
1532
shader_fully_loaded = false;
1533
bool changed = false;
1534
VisualShader *visual_shader_ptr = Object::cast_to<VisualShader>(p_shader.ptr());
1535
if (visual_shader_ptr) {
1536
if (visual_shader.is_null()) {
1537
changed = true;
1538
} else {
1539
if (visual_shader.ptr() != visual_shader_ptr) {
1540
changed = true;
1541
}
1542
}
1543
visual_shader = p_shader;
1544
graph_plugin->register_shader(visual_shader.ptr());
1545
1546
visual_shader->connect_changed(callable_mp(this, &VisualShaderEditor::_update_preview));
1547
_set_mode(visual_shader->get_mode());
1548
1549
preview_material->set_shader(visual_shader);
1550
_update_nodes();
1551
} else {
1552
if (visual_shader.is_valid()) {
1553
visual_shader->disconnect_changed(callable_mp(this, &VisualShaderEditor::_update_preview));
1554
}
1555
visual_shader.unref();
1556
}
1557
1558
if (visual_shader.is_null()) {
1559
hide();
1560
} else {
1561
if (changed) { // to avoid tree collapse
1562
_update_varying_tree();
1563
_update_options_menu();
1564
_update_preview();
1565
_update_graph();
1566
callable_mp(this, &VisualShaderEditor::_restore_editor_state).call_deferred();
1567
}
1568
}
1569
}
1570
1571
void VisualShaderEditor::use_menu_bar(MenuButton *p_file_menu) {
1572
p_file_menu->set_switch_on_hover(false);
1573
toolbar_hflow->add_child(p_file_menu);
1574
toolbar_hflow->move_child(p_file_menu, 2); // Toggle Files Panel button + separator.
1575
}
1576
1577
void VisualShaderEditor::apply_shaders() {
1578
// Stub. TODO: Implement apply_shaders in visual shaders for parity with text shaders.
1579
}
1580
1581
bool VisualShaderEditor::is_unsaved() const {
1582
// Stub. TODO: Implement is_unsaved in visual shaders for parity with text shaders.
1583
return false;
1584
}
1585
1586
void VisualShaderEditor::save_external_data(const String &p_str) {
1587
ResourceSaver::save(visual_shader, visual_shader->get_path());
1588
}
1589
1590
void VisualShaderEditor::validate_script() {
1591
if (visual_shader.is_valid()) {
1592
_update_nodes();
1593
}
1594
}
1595
1596
void VisualShaderEditor::save_editor_layout() {
1597
const String id_string = _get_cache_id_string();
1598
1599
const String offset_cache_key = _get_cache_key("offset");
1600
const String zoom_cache_key = _get_cache_key("zoom");
1601
vs_editor_cache->set_value(id_string, offset_cache_key, graph->get_scroll_offset() / EDSCALE);
1602
vs_editor_cache->set_value(id_string, zoom_cache_key, graph->get_zoom());
1603
vs_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
1604
}
1605
1606
void VisualShaderEditor::set_current_shader_type(VisualShader::Type p_type) {
1607
current_type = p_type;
1608
1609
const String id_string = _get_cache_id_string();
1610
1611
vs_editor_cache->set_value(id_string, "edited_type", p_type);
1612
vs_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
1613
1614
const String offset_cache_key = _get_cache_key("offset");
1615
const String zoom_cache_key = _get_cache_key("zoom");
1616
const Vector2 saved_scroll_offset = vs_editor_cache->get_value(id_string, offset_cache_key, Vector2());
1617
const real_t saved_zoom = vs_editor_cache->get_value(id_string, zoom_cache_key, 1.0);
1618
1619
graph->set_scroll_offset(saved_scroll_offset);
1620
graph->set_zoom(saved_zoom);
1621
}
1622
1623
VisualShader::Type VisualShaderEditor::get_current_shader_type() const {
1624
return current_type;
1625
}
1626
1627
void VisualShaderEditor::add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
1628
if (plugins.has(p_plugin)) {
1629
return;
1630
}
1631
plugins.push_back(p_plugin);
1632
}
1633
1634
void VisualShaderEditor::remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
1635
plugins.erase(p_plugin);
1636
}
1637
1638
void VisualShaderEditor::clear_custom_types() {
1639
for (int i = 0; i < add_options.size(); i++) {
1640
if (add_options[i].is_custom) {
1641
add_options.remove_at(i);
1642
i--;
1643
}
1644
}
1645
}
1646
1647
void VisualShaderEditor::add_custom_type(const String &p_name, const String &p_type, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend) {
1648
ERR_FAIL_COND(!p_name.is_valid_ascii_identifier());
1649
ERR_FAIL_COND(p_type.is_empty() && p_script.is_null());
1650
1651
for (int i = 0; i < add_options.size(); i++) {
1652
const AddOption &op = add_options[i];
1653
1654
if (op.is_custom) {
1655
if (!p_type.is_empty()) {
1656
if (op.type == p_type) {
1657
return;
1658
}
1659
} else if (op.script == p_script) {
1660
return;
1661
}
1662
}
1663
}
1664
1665
AddOption ao;
1666
ao.name = p_name;
1667
ao.type = p_type;
1668
ao.script = p_script;
1669
ao.return_type = p_return_icon_type;
1670
ao.description = p_description;
1671
ao.category = p_category;
1672
ao.highend = p_highend;
1673
ao.is_custom = true;
1674
ao.is_native = !p_type.is_empty();
1675
1676
bool begin = false;
1677
String root = p_category.get_slicec('/', 0);
1678
1679
for (int i = 0; i < add_options.size(); i++) {
1680
if (add_options[i].is_custom) {
1681
if (add_options[i].category == root) {
1682
if (!begin) {
1683
begin = true;
1684
}
1685
} else {
1686
if (begin) {
1687
add_options.insert(i, ao);
1688
return;
1689
}
1690
}
1691
}
1692
}
1693
add_options.push_back(ao);
1694
}
1695
1696
Dictionary VisualShaderEditor::get_custom_node_data(Ref<VisualShaderNodeCustom> &p_custom_node) {
1697
Dictionary dict;
1698
dict["script"] = p_custom_node->get_script();
1699
dict["name"] = p_custom_node->_get_name();
1700
dict["description"] = p_custom_node->_get_description();
1701
dict["return_icon_type"] = p_custom_node->_get_return_icon_type();
1702
dict["highend"] = p_custom_node->_is_highend();
1703
1704
String category = p_custom_node->_get_category();
1705
category = category.rstrip("/");
1706
category = category.lstrip("/");
1707
category = "Addons/" + category;
1708
if (p_custom_node->has_method("_get_subcategory")) {
1709
String subcategory = (String)p_custom_node->call("_get_subcategory");
1710
if (!subcategory.is_empty()) {
1711
category += "/" + subcategory;
1712
}
1713
}
1714
dict["category"] = category;
1715
1716
return dict;
1717
}
1718
1719
void VisualShaderEditor::_get_current_mode_limits(int &r_begin_type, int &r_end_type) const {
1720
switch (visual_shader->get_mode()) {
1721
case Shader::MODE_CANVAS_ITEM:
1722
case Shader::MODE_SPATIAL: {
1723
r_begin_type = VisualShader::TYPE_VERTEX;
1724
r_end_type = VisualShader::TYPE_START;
1725
} break;
1726
case Shader::MODE_PARTICLES: {
1727
r_begin_type = VisualShader::TYPE_START;
1728
r_end_type = VisualShader::TYPE_SKY;
1729
} break;
1730
case Shader::MODE_SKY: {
1731
r_begin_type = VisualShader::TYPE_SKY;
1732
r_end_type = VisualShader::TYPE_FOG;
1733
} break;
1734
case Shader::MODE_FOG: {
1735
r_begin_type = VisualShader::TYPE_FOG;
1736
r_end_type = VisualShader::TYPE_TEXTURE_BLIT;
1737
} break;
1738
case Shader::MODE_TEXTURE_BLIT: {
1739
r_begin_type = VisualShader::TYPE_TEXTURE_BLIT;
1740
r_end_type = VisualShader::TYPE_MAX;
1741
} break;
1742
default: {
1743
} break;
1744
}
1745
}
1746
1747
void VisualShaderEditor::_script_created(const Ref<Script> &p_script) {
1748
if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
1749
return;
1750
}
1751
Ref<VisualShaderNodeCustom> ref;
1752
ref.instantiate();
1753
ref->set_script(p_script);
1754
1755
Dictionary dict = get_custom_node_data(ref);
1756
add_custom_type(dict["name"], String(), dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
1757
1758
_update_options_menu();
1759
}
1760
1761
void VisualShaderEditor::_update_custom_script(const Ref<Script> &p_script) {
1762
if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
1763
return;
1764
}
1765
1766
Ref<VisualShaderNodeCustom> ref;
1767
ref.instantiate();
1768
ref->set_script(p_script);
1769
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
1770
for (int i = 0; i < add_options.size(); i++) {
1771
if (add_options[i].is_custom && add_options[i].script == p_script) {
1772
add_options.remove_at(i);
1773
_update_options_menu();
1774
// TODO: Make indication for the existed custom nodes with that script on graph to be disabled.
1775
break;
1776
}
1777
}
1778
return;
1779
}
1780
Dictionary dict = get_custom_node_data(ref);
1781
1782
bool found_type = false;
1783
bool need_rebuild = false;
1784
1785
for (int i = custom_node_option_idx; i < add_options.size(); i++) {
1786
if (add_options[i].script == p_script) {
1787
found_type = true;
1788
1789
add_options.write[i].name = dict["name"];
1790
add_options.write[i].return_type = dict["return_icon_type"];
1791
add_options.write[i].description = dict["description"];
1792
add_options.write[i].category = dict["category"];
1793
add_options.write[i].highend = dict["highend"];
1794
1795
int begin_type = 0;
1796
int end_type = 0;
1797
_get_current_mode_limits(begin_type, end_type);
1798
1799
for (int t = begin_type; t < end_type; t++) {
1800
VisualShader::Type type = (VisualShader::Type)t;
1801
Vector<int> nodes = visual_shader->get_node_list(type);
1802
1803
List<VisualShader::Connection> node_connections;
1804
visual_shader->get_node_connections(type, &node_connections);
1805
1806
List<VisualShader::Connection> custom_node_input_connections;
1807
List<VisualShader::Connection> custom_node_output_connections;
1808
1809
for (const VisualShader::Connection &E : node_connections) {
1810
int from = E.from_node;
1811
int from_port = E.from_port;
1812
int to = E.to_node;
1813
int to_port = E.to_port;
1814
1815
if (graph_plugin->get_node_script(from) == p_script) {
1816
custom_node_output_connections.push_back({ from, from_port, to, to_port });
1817
} else if (graph_plugin->get_node_script(to) == p_script) {
1818
custom_node_input_connections.push_back({ from, from_port, to, to_port });
1819
}
1820
}
1821
1822
for (int node_id : nodes) {
1823
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
1824
if (vsnode.is_null()) {
1825
continue;
1826
}
1827
Ref<VisualShaderNodeCustom> custom_node = vsnode;
1828
if (custom_node.is_null() || custom_node->get_script() != p_script) {
1829
continue;
1830
}
1831
need_rebuild = true;
1832
1833
// Removes invalid connections.
1834
{
1835
int prev_input_port_count = custom_node->get_input_port_count();
1836
int prev_output_port_count = custom_node->get_output_port_count();
1837
1838
custom_node->update_ports();
1839
1840
int input_port_count = custom_node->get_input_port_count();
1841
int output_port_count = custom_node->get_output_port_count();
1842
1843
if (output_port_count != prev_output_port_count) {
1844
for (const VisualShader::Connection &E : custom_node_output_connections) {
1845
int from = E.from_node;
1846
int from_idx = E.from_port;
1847
int to = E.to_node;
1848
int to_idx = E.to_port;
1849
1850
if (from_idx >= output_port_count) {
1851
visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
1852
graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
1853
}
1854
}
1855
}
1856
if (input_port_count != prev_input_port_count) {
1857
for (const VisualShader::Connection &E : custom_node_input_connections) {
1858
int from = E.from_node;
1859
int from_idx = E.from_port;
1860
int to = E.to_node;
1861
int to_idx = E.to_port;
1862
1863
if (to_idx >= input_port_count) {
1864
visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
1865
graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
1866
}
1867
}
1868
}
1869
}
1870
1871
graph_plugin->update_node(type, node_id);
1872
}
1873
}
1874
break;
1875
}
1876
}
1877
1878
if (!found_type) {
1879
add_custom_type(dict["name"], String(), dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
1880
}
1881
1882
// To prevent updating options multiple times when multiple scripts are saved.
1883
if (!_block_update_options_menu) {
1884
_block_update_options_menu = true;
1885
1886
callable_mp(this, &VisualShaderEditor::_update_options_menu_deferred);
1887
}
1888
1889
// To prevent rebuilding the shader multiple times when multiple scripts are saved.
1890
if (need_rebuild && !_block_rebuild_shader) {
1891
_block_rebuild_shader = true;
1892
1893
callable_mp(this, &VisualShaderEditor::_rebuild_shader_deferred);
1894
}
1895
}
1896
1897
void VisualShaderEditor::_resource_saved(const Ref<Resource> &p_resource) {
1898
_update_custom_script(Ref<Script>(p_resource.ptr()));
1899
}
1900
1901
void VisualShaderEditor::_resources_removed() {
1902
bool has_any_instance = false;
1903
1904
for (const Ref<Script> &scr : custom_scripts_to_delete) {
1905
for (int i = custom_node_option_idx; i < add_options.size(); i++) {
1906
if (add_options[i].script == scr) {
1907
add_options.remove_at(i);
1908
1909
// Removes all node instances using that script from the graph.
1910
{
1911
int begin_type = 0;
1912
int end_type = 0;
1913
_get_current_mode_limits(begin_type, end_type);
1914
1915
for (int t = begin_type; t < end_type; t++) {
1916
VisualShader::Type type = (VisualShader::Type)t;
1917
1918
List<VisualShader::Connection> node_connections;
1919
visual_shader->get_node_connections(type, &node_connections);
1920
1921
for (const VisualShader::Connection &E : node_connections) {
1922
int from = E.from_node;
1923
int from_port = E.from_port;
1924
int to = E.to_node;
1925
int to_port = E.to_port;
1926
1927
if (graph_plugin->get_node_script(from) == scr || graph_plugin->get_node_script(to) == scr) {
1928
visual_shader->disconnect_nodes(type, from, from_port, to, to_port);
1929
graph_plugin->disconnect_nodes(type, from, from_port, to, to_port);
1930
}
1931
}
1932
1933
Vector<int> nodes = visual_shader->get_node_list(type);
1934
for (int node_id : nodes) {
1935
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
1936
if (vsnode.is_null()) {
1937
continue;
1938
}
1939
Ref<VisualShaderNodeCustom> custom_node = vsnode;
1940
if (custom_node.is_null() || custom_node->get_script() != scr) {
1941
continue;
1942
}
1943
visual_shader->remove_node(type, node_id);
1944
graph_plugin->remove_node(type, node_id, false);
1945
1946
has_any_instance = true;
1947
}
1948
}
1949
}
1950
1951
break;
1952
}
1953
}
1954
}
1955
if (has_any_instance) {
1956
EditorUndoRedoManager::get_singleton()->clear_history(); // Need to clear undo history, otherwise it may lead to hard-detected errors and crashes (since the script was removed).
1957
ResourceSaver::save(visual_shader, visual_shader->get_path());
1958
}
1959
_update_options_menu();
1960
1961
custom_scripts_to_delete.clear();
1962
pending_custom_scripts_to_delete = false;
1963
}
1964
1965
void VisualShaderEditor::_resource_removed(const Ref<Resource> &p_resource) {
1966
Ref<Script> scr = Ref<Script>(p_resource.ptr());
1967
if (scr.is_null() || scr->get_instance_base_type() != "VisualShaderNodeCustom") {
1968
return;
1969
}
1970
1971
custom_scripts_to_delete.push_back(scr);
1972
1973
if (!pending_custom_scripts_to_delete) {
1974
pending_custom_scripts_to_delete = true;
1975
callable_mp(this, &VisualShaderEditor::_resources_removed).call_deferred();
1976
}
1977
}
1978
1979
void VisualShaderEditor::_update_options_menu_deferred() {
1980
_update_options_menu();
1981
1982
_block_update_options_menu = false;
1983
}
1984
1985
void VisualShaderEditor::_rebuild_shader_deferred() {
1986
if (visual_shader.is_valid()) {
1987
visual_shader->rebuild();
1988
}
1989
1990
_block_rebuild_shader = false;
1991
}
1992
1993
bool VisualShaderEditor::_is_available(int p_mode) {
1994
int current_mode = edit_type->get_selected();
1995
1996
if (p_mode != -1) {
1997
switch (current_mode) {
1998
case 0: // Vertex / Emit
1999
current_mode = 1;
2000
break;
2001
case 1: // Fragment / Process
2002
current_mode = 2;
2003
break;
2004
case 2: // Light / Collide
2005
current_mode = 4;
2006
break;
2007
default:
2008
break;
2009
}
2010
}
2011
2012
return (p_mode == -1 || (p_mode & current_mode) != 0);
2013
}
2014
2015
bool VisualShaderEditor::_update_preview_parameter_tree() {
2016
bool found = false;
2017
bool use_filter = !param_filter_name.is_empty();
2018
2019
parameters->clear();
2020
TreeItem *root = parameters->create_item();
2021
2022
for (const KeyValue<String, PropertyInfo> &prop : parameter_props) {
2023
String param_name = prop.value.name;
2024
if (use_filter && !param_name.containsn(param_filter_name)) {
2025
continue;
2026
}
2027
2028
TreeItem *item = parameters->create_item(root);
2029
item->set_text(0, param_name);
2030
item->set_meta("id", param_name);
2031
2032
if (param_name == selected_param_id) {
2033
parameters->set_selected(item);
2034
found = true;
2035
}
2036
2037
if (prop.value.type == Variant::OBJECT) {
2038
item->set_icon(0, get_editor_theme_icon(SNAME("ImageTexture")));
2039
} else {
2040
item->set_icon(0, get_editor_theme_icon(Variant::get_type_name(prop.value.type)));
2041
}
2042
}
2043
2044
return found;
2045
}
2046
2047
void VisualShaderEditor::_preview_tools_menu_option(int p_idx) {
2048
ShaderMaterial *src_mat = nullptr;
2049
2050
if (p_idx == COPY_PARAMS_FROM_MATERIAL || p_idx == PASTE_PARAMS_TO_MATERIAL) {
2051
for (int i = EditorNode::get_singleton()->get_editor_selection_history()->get_path_size() - 1; i >= 0; i--) {
2052
Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_selection_history()->get_path_object(i));
2053
ShaderMaterial *src_mat2;
2054
if (!object) {
2055
continue;
2056
}
2057
if (object->has_method("get_material_override")) { // Trying to get material from MeshInstance.
2058
src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material_override"));
2059
} else if (object->has_method("get_material")) { // From CanvasItem/Node2D.
2060
src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material"));
2061
} else {
2062
src_mat2 = Object::cast_to<ShaderMaterial>(object);
2063
}
2064
2065
if (src_mat2 && src_mat2->get_shader().is_valid() && src_mat2->get_shader() == visual_shader) {
2066
src_mat = src_mat2;
2067
break;
2068
}
2069
}
2070
}
2071
2072
switch (p_idx) {
2073
case COPY_PARAMS_FROM_MATERIAL:
2074
if (src_mat) {
2075
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2076
undo_redo->create_action(TTR("Copy Preview Shader Parameters From Material"));
2077
2078
List<PropertyInfo> params;
2079
preview_material->get_shader()->get_shader_uniform_list(&params);
2080
for (const PropertyInfo &E : params) {
2081
undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, src_mat->get_shader_parameter(E.name));
2082
undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, preview_material->get_shader_parameter(E.name));
2083
}
2084
2085
undo_redo->commit_action();
2086
}
2087
break;
2088
case PASTE_PARAMS_TO_MATERIAL:
2089
if (src_mat) {
2090
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2091
undo_redo->create_action(TTR("Paste Preview Shader Parameters To Material"));
2092
2093
List<PropertyInfo> params;
2094
preview_material->get_shader()->get_shader_uniform_list(&params);
2095
for (const PropertyInfo &E : params) {
2096
undo_redo->add_do_method(src_mat, "set_shader_parameter", E.name, preview_material->get_shader_parameter(E.name));
2097
undo_redo->add_undo_method(src_mat, "set_shader_parameter", E.name, src_mat->get_shader_parameter(E.name));
2098
}
2099
2100
undo_redo->commit_action();
2101
}
2102
break;
2103
default:
2104
break;
2105
}
2106
}
2107
2108
void VisualShaderEditor::_clear_preview_param() {
2109
selected_param_id = "";
2110
current_prop = nullptr;
2111
2112
if (param_vbox2->get_child_count() > 0) {
2113
param_vbox2->remove_child(param_vbox2->get_child(0));
2114
}
2115
2116
param_vbox->hide();
2117
}
2118
2119
void VisualShaderEditor::_update_preview_parameter_list() {
2120
material_editor->edit(preview_material.ptr(), env);
2121
2122
List<PropertyInfo> properties;
2123
RenderingServer::get_singleton()->get_shader_parameter_list(visual_shader->get_rid(), &properties);
2124
2125
HashSet<String> params_to_remove;
2126
for (const KeyValue<String, PropertyInfo> &E : parameter_props) {
2127
params_to_remove.insert(E.key);
2128
}
2129
parameter_props.clear();
2130
2131
for (const PropertyInfo &prop : properties) {
2132
String param_name = prop.name;
2133
2134
if (visual_shader->_has_preview_shader_parameter(param_name)) {
2135
preview_material->set_shader_parameter(param_name, visual_shader->_get_preview_shader_parameter(param_name));
2136
} else {
2137
preview_material->set_shader_parameter(param_name, RenderingServer::get_singleton()->shader_get_parameter_default(visual_shader->get_rid(), param_name));
2138
}
2139
2140
parameter_props.insert(param_name, prop);
2141
params_to_remove.erase(param_name);
2142
2143
if (param_name == selected_param_id) {
2144
current_prop->update_property();
2145
current_prop->update_editor_property_status();
2146
current_prop->update_cache();
2147
}
2148
}
2149
2150
_update_preview_parameter_tree();
2151
2152
// Removes invalid parameters.
2153
for (const String &param_name : params_to_remove) {
2154
preview_material->set_shader_parameter(param_name, Variant());
2155
2156
if (visual_shader->_has_preview_shader_parameter(param_name)) {
2157
visual_shader->_set_preview_shader_parameter(param_name, Variant());
2158
}
2159
2160
if (param_name == selected_param_id) {
2161
_clear_preview_param();
2162
}
2163
}
2164
}
2165
2166
void VisualShaderEditor::_update_nodes() {
2167
clear_custom_types();
2168
Dictionary added;
2169
2170
// Add GDScript classes.
2171
{
2172
LocalVector<StringName> class_list;
2173
ScriptServer::get_global_class_list(class_list);
2174
2175
for (const StringName &class_name : class_list) {
2176
if (ScriptServer::get_global_class_native_base(class_name) == "VisualShaderNodeCustom") {
2177
String script_path = ScriptServer::get_global_class_path(class_name);
2178
Ref<Resource> res = ResourceLoader::load(script_path);
2179
ERR_CONTINUE(res.is_null());
2180
ERR_CONTINUE(!res->is_class("Script"));
2181
Ref<Script> scr = Ref<Script>(res);
2182
2183
Ref<VisualShaderNodeCustom> ref;
2184
ref.instantiate();
2185
ref->set_script(scr);
2186
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2187
continue;
2188
}
2189
Dictionary dict = get_custom_node_data(ref);
2190
dict["type"] = String();
2191
2192
String key;
2193
key = String(dict["category"]) + "/" + String(dict["name"]);
2194
2195
added[key] = dict;
2196
}
2197
}
2198
}
2199
2200
// Add GDExtension classes.
2201
{
2202
LocalVector<StringName> class_list;
2203
ClassDB::get_class_list(class_list);
2204
2205
for (const StringName &class_name : class_list) {
2206
if (ClassDB::get_parent_class(class_name) == "VisualShaderNodeCustom") {
2207
Object *instance = ClassDB::instantiate(class_name);
2208
Ref<VisualShaderNodeCustom> ref = Object::cast_to<VisualShaderNodeCustom>(instance);
2209
ERR_CONTINUE(ref.is_null());
2210
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2211
continue;
2212
}
2213
Dictionary dict = get_custom_node_data(ref);
2214
dict["type"] = class_name;
2215
dict["script"] = Ref<Script>();
2216
2217
String key;
2218
key = String(dict["category"]) + "/" + String(dict["name"]);
2219
2220
added[key] = dict;
2221
}
2222
}
2223
}
2224
2225
// Disables not-supported copied items.
2226
{
2227
for (CopyItem &item : copy_items_buffer) {
2228
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(item.node.ptr());
2229
2230
if (custom.is_valid()) {
2231
if (!custom->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2232
item.disabled = true;
2233
} else {
2234
item.disabled = false;
2235
}
2236
} else {
2237
for (int i = 0; i < add_options.size(); i++) {
2238
if (add_options[i].type == item.node->get_class_name()) {
2239
if ((add_options[i].func != visual_shader->get_mode() && add_options[i].func != -1) || !_is_available(add_options[i].mode)) {
2240
item.disabled = true;
2241
} else {
2242
item.disabled = false;
2243
}
2244
break;
2245
}
2246
}
2247
}
2248
}
2249
}
2250
2251
LocalVector<Variant> keys = added.get_key_list();
2252
keys.sort_custom<StringLikeVariantOrder>();
2253
2254
for (const Variant &key : keys) {
2255
const Dictionary &value = (Dictionary)added[key];
2256
2257
add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]);
2258
}
2259
2260
_update_options_menu();
2261
}
2262
2263
String VisualShaderEditor::_get_description(int p_idx) {
2264
return add_options[p_idx].description;
2265
}
2266
2267
void VisualShaderEditor::_update_options_menu() {
2268
node_desc->set_text("");
2269
highend_label->set_visible(false);
2270
members_dialog->get_ok_button()->set_disabled(true);
2271
2272
members->clear();
2273
TreeItem *root = members->create_item();
2274
2275
String filter = node_filter->get_text().strip_edges();
2276
bool use_filter = !filter.is_empty();
2277
2278
bool is_first_item = true;
2279
2280
Color unsupported_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
2281
Color supported_color = get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
2282
2283
static bool low_driver = GLOBAL_GET("rendering/renderer/rendering_method") == "gl_compatibility";
2284
2285
HashMap<String, TreeItem *> folders;
2286
2287
int current_func = -1;
2288
2289
if (visual_shader.is_valid()) {
2290
current_func = visual_shader->get_mode();
2291
}
2292
2293
Vector<AddOption> custom_options;
2294
Vector<AddOption> embedded_options;
2295
2296
static Vector<String> type_filter_exceptions;
2297
if (type_filter_exceptions.is_empty()) {
2298
type_filter_exceptions.append("VisualShaderNodeExpression");
2299
type_filter_exceptions.append("VisualShaderNodeReroute");
2300
}
2301
2302
for (int i = 0; i < add_options.size(); i++) {
2303
if (!use_filter || add_options[i].name.containsn(filter)) {
2304
// port type filtering
2305
if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX || members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2306
Ref<VisualShaderNode> vsn;
2307
int check_result = 0;
2308
2309
if (!add_options[i].is_custom) {
2310
vsn = Ref<VisualShaderNode>(Object::cast_to<VisualShaderNode>(ClassDB::instantiate(add_options[i].type)));
2311
if (vsn.is_null()) {
2312
continue;
2313
}
2314
2315
if (type_filter_exceptions.has(add_options[i].type)) {
2316
check_result = 1;
2317
}
2318
2319
Ref<VisualShaderNodeInput> input = Object::cast_to<VisualShaderNodeInput>(vsn.ptr());
2320
if (input.is_valid()) {
2321
input->set_shader_mode(visual_shader->get_mode());
2322
input->set_shader_type(get_current_shader_type());
2323
if (!add_options[i].ops.is_empty() && add_options[i].ops[0].is_string()) {
2324
input->set_input_name((String)add_options[i].ops[0]);
2325
}
2326
}
2327
2328
Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(vsn.ptr());
2329
if (expression.is_valid()) {
2330
if (members_input_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
2331
check_result = -1; // expressions creates a port with required type automatically (except for sampler output)
2332
}
2333
}
2334
2335
Ref<VisualShaderNodeParameterRef> parameter_ref = Object::cast_to<VisualShaderNodeParameterRef>(vsn.ptr());
2336
if (parameter_ref.is_valid() && parameter_ref->is_shader_valid()) {
2337
check_result = -1;
2338
2339
if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2340
for (int j = 0; j < parameter_ref->get_parameters_count(); j++) {
2341
if (visual_shader->is_port_types_compatible(parameter_ref->get_port_type_by_index(j), members_input_port_type)) {
2342
check_result = 1;
2343
break;
2344
}
2345
}
2346
}
2347
}
2348
} else {
2349
check_result = 1;
2350
}
2351
2352
if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2353
if (check_result == 0) {
2354
for (int j = 0; j < vsn->get_input_port_count(); j++) {
2355
if (visual_shader->is_port_types_compatible(vsn->get_input_port_type(j), members_output_port_type)) {
2356
check_result = 1;
2357
break;
2358
}
2359
}
2360
}
2361
2362
if (check_result != 1) {
2363
continue;
2364
}
2365
}
2366
if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2367
if (check_result == 0) {
2368
for (int j = 0; j < vsn->get_output_port_count(); j++) {
2369
if (visual_shader->is_port_types_compatible(vsn->get_output_port_type(j), members_input_port_type)) {
2370
check_result = 1;
2371
break;
2372
}
2373
}
2374
}
2375
2376
if (check_result != 1) {
2377
continue;
2378
}
2379
}
2380
}
2381
if ((add_options[i].func != current_func && add_options[i].func != -1) || !_is_available(add_options[i].mode)) {
2382
continue;
2383
}
2384
add_options[i].temp_idx = i; // save valid id
2385
if (add_options[i].is_custom) {
2386
custom_options.push_back(add_options[i]);
2387
} else {
2388
embedded_options.push_back(add_options[i]);
2389
}
2390
}
2391
}
2392
Vector<AddOption> options;
2393
SortArray<AddOption, _OptionComparator> sorter;
2394
sorter.sort(custom_options.ptrw(), custom_options.size());
2395
2396
options.append_array(custom_options);
2397
options.append_array(embedded_options);
2398
2399
for (int i = 0; i < options.size(); i++) {
2400
String path = options[i].category;
2401
Vector<String> subfolders = path.split("/");
2402
TreeItem *category = nullptr;
2403
2404
if (!folders.has(path)) {
2405
category = root;
2406
String path_temp = "";
2407
for (int j = 0; j < subfolders.size(); j++) {
2408
path_temp += subfolders[j];
2409
if (!folders.has(path_temp)) {
2410
category = members->create_item(category);
2411
category->set_selectable(0, false);
2412
category->set_collapsed(!use_filter);
2413
category->set_text(0, subfolders[j]);
2414
folders.insert(path_temp, category);
2415
} else {
2416
category = folders[path_temp];
2417
}
2418
}
2419
} else {
2420
category = folders[path];
2421
}
2422
2423
TreeItem *item = members->create_item(category);
2424
if (options[i].highend && low_driver) {
2425
item->set_custom_color(0, unsupported_color);
2426
} else if (options[i].highend) {
2427
item->set_custom_color(0, supported_color);
2428
}
2429
item->set_text(0, options[i].name);
2430
if (is_first_item && use_filter) {
2431
item->select(0);
2432
node_desc->set_text(options[i].description);
2433
is_first_item = false;
2434
2435
members_dialog->get_ok_button()->set_disabled(false);
2436
}
2437
switch (options[i].return_type) {
2438
case VisualShaderNode::PORT_TYPE_SCALAR:
2439
item->set_icon(0, get_editor_theme_icon(SNAME("float")));
2440
break;
2441
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
2442
item->set_icon(0, get_editor_theme_icon(SNAME("int")));
2443
break;
2444
case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
2445
item->set_icon(0, get_editor_theme_icon(SNAME("uint")));
2446
break;
2447
case VisualShaderNode::PORT_TYPE_VECTOR_2D:
2448
item->set_icon(0, get_editor_theme_icon(SNAME("Vector2")));
2449
break;
2450
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
2451
item->set_icon(0, get_editor_theme_icon(SNAME("Vector3")));
2452
break;
2453
case VisualShaderNode::PORT_TYPE_VECTOR_4D:
2454
item->set_icon(0, get_editor_theme_icon(SNAME("Vector4")));
2455
break;
2456
case VisualShaderNode::PORT_TYPE_BOOLEAN:
2457
item->set_icon(0, get_editor_theme_icon(SNAME("bool")));
2458
break;
2459
case VisualShaderNode::PORT_TYPE_TRANSFORM:
2460
item->set_icon(0, get_editor_theme_icon(SNAME("Transform3D")));
2461
break;
2462
case VisualShaderNode::PORT_TYPE_SAMPLER:
2463
item->set_icon(0, get_editor_theme_icon(SNAME("ImageTexture")));
2464
break;
2465
default:
2466
break;
2467
}
2468
item->set_meta("id", options[i].temp_idx);
2469
}
2470
}
2471
2472
void VisualShaderEditor::_set_mode(int p_which) {
2473
if (p_which == VisualShader::MODE_SKY) {
2474
edit_type_standard->set_visible(false);
2475
edit_type_particles->set_visible(false);
2476
edit_type_sky->set_visible(true);
2477
edit_type_fog->set_visible(false);
2478
edit_type_texture_blit->set_visible(false);
2479
edit_type = edit_type_sky;
2480
custom_mode_box->set_visible(false);
2481
varying_button->hide();
2482
mode = MODE_FLAGS_SKY;
2483
} else if (p_which == VisualShader::MODE_FOG) {
2484
edit_type_standard->set_visible(false);
2485
edit_type_particles->set_visible(false);
2486
edit_type_sky->set_visible(false);
2487
edit_type_fog->set_visible(true);
2488
edit_type_texture_blit->set_visible(false);
2489
edit_type = edit_type_fog;
2490
custom_mode_box->set_visible(false);
2491
varying_button->hide();
2492
mode = MODE_FLAGS_FOG;
2493
} else if (p_which == VisualShader::MODE_PARTICLES) {
2494
edit_type_standard->set_visible(false);
2495
edit_type_particles->set_visible(true);
2496
edit_type_sky->set_visible(false);
2497
edit_type_fog->set_visible(false);
2498
edit_type_texture_blit->set_visible(false);
2499
edit_type = edit_type_particles;
2500
if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
2501
custom_mode_box->set_visible(false);
2502
} else {
2503
custom_mode_box->set_visible(true);
2504
}
2505
varying_button->hide();
2506
mode = MODE_FLAGS_PARTICLES;
2507
} else if (p_which == VisualShader::MODE_TEXTURE_BLIT) {
2508
edit_type_standard->set_visible(false);
2509
edit_type_particles->set_visible(false);
2510
edit_type_sky->set_visible(false);
2511
edit_type_fog->set_visible(false);
2512
edit_type_texture_blit->set_visible(true);
2513
edit_type = edit_type_texture_blit;
2514
if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
2515
custom_mode_box->set_visible(false);
2516
} else {
2517
custom_mode_box->set_visible(true);
2518
}
2519
varying_button->hide();
2520
mode = MODE_FLAGS_TEXTURE_BLIT;
2521
} else {
2522
edit_type_particles->set_visible(false);
2523
edit_type_standard->set_visible(true);
2524
edit_type_sky->set_visible(false);
2525
edit_type_fog->set_visible(false);
2526
edit_type_texture_blit->set_visible(false);
2527
edit_type = edit_type_standard;
2528
custom_mode_box->set_visible(false);
2529
varying_button->show();
2530
mode = MODE_FLAGS_SPATIAL_CANVASITEM;
2531
}
2532
2533
const String id_string = _get_cache_id_string();
2534
2535
int default_type = VisualShader::TYPE_VERTEX;
2536
int upper_type = VisualShader::TYPE_START;
2537
if (mode & MODE_FLAGS_PARTICLES) {
2538
default_type = VisualShader::TYPE_START;
2539
upper_type = VisualShader::TYPE_SKY;
2540
} else if (mode & MODE_FLAGS_SKY) {
2541
default_type = VisualShader::TYPE_SKY;
2542
upper_type = VisualShader::TYPE_FOG;
2543
} else if (mode & MODE_FLAGS_FOG) {
2544
default_type = VisualShader::TYPE_FOG;
2545
upper_type = VisualShader::TYPE_TEXTURE_BLIT;
2546
} else if (mode & MODE_FLAGS_TEXTURE_BLIT) {
2547
default_type = VisualShader::TYPE_TEXTURE_BLIT;
2548
upper_type = VisualShader::TYPE_MAX;
2549
}
2550
2551
int saved_type = vs_editor_cache->get_value(id_string, "edited_type", default_type);
2552
if (saved_type >= upper_type || saved_type < default_type) {
2553
saved_type = default_type;
2554
}
2555
2556
if (mode & MODE_FLAGS_PARTICLES && saved_type - default_type >= 3) {
2557
edit_type->select(saved_type - default_type - 3);
2558
custom_mode_box->set_pressed(true);
2559
} else {
2560
edit_type->select(saved_type - default_type);
2561
}
2562
set_current_shader_type((VisualShader::Type)saved_type);
2563
}
2564
2565
Size2 VisualShaderEditor::get_minimum_size() const {
2566
return Size2(10, 200);
2567
}
2568
2569
void VisualShaderEditor::update_toggle_files_button() {
2570
ERR_FAIL_NULL(toggle_files_list);
2571
bool forward = toggle_files_list->is_visible() == is_layout_rtl();
2572
toggle_files_button->set_button_icon(get_editor_theme_icon(forward ? SNAME("Forward") : SNAME("Back")));
2573
toggle_files_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Files Panel"), ED_GET_SHORTCUT("script_editor/toggle_files_panel")->get_as_text()));
2574
}
2575
2576
void VisualShaderEditor::_draw_color_over_button(Object *p_obj, Color p_color) {
2577
Button *button = Object::cast_to<Button>(p_obj);
2578
if (!button) {
2579
return;
2580
}
2581
2582
Ref<StyleBox> normal = get_theme_stylebox(CoreStringName(normal), SNAME("Button"));
2583
button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
2584
}
2585
2586
void VisualShaderEditor::_update_parameters(bool p_update_refs) {
2587
VisualShaderNodeParameterRef::clear_parameters(visual_shader->get_rid());
2588
2589
for (int t = 0; t < VisualShader::TYPE_MAX; t++) {
2590
Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t);
2591
for (int i = 0; i < tnodes.size(); i++) {
2592
Ref<VisualShaderNode> vsnode = visual_shader->get_node((VisualShader::Type)t, tnodes[i]);
2593
Ref<VisualShaderNodeParameter> parameter = vsnode;
2594
2595
if (parameter.is_valid()) {
2596
Ref<VisualShaderNodeFloatParameter> float_parameter = vsnode;
2597
Ref<VisualShaderNodeIntParameter> int_parameter = vsnode;
2598
Ref<VisualShaderNodeUIntParameter> uint_parameter = vsnode;
2599
Ref<VisualShaderNodeVec2Parameter> vec2_parameter = vsnode;
2600
Ref<VisualShaderNodeVec3Parameter> vec3_parameter = vsnode;
2601
Ref<VisualShaderNodeVec4Parameter> vec4_parameter = vsnode;
2602
Ref<VisualShaderNodeColorParameter> color_parameter = vsnode;
2603
Ref<VisualShaderNodeBooleanParameter> boolean_parameter = vsnode;
2604
Ref<VisualShaderNodeTransformParameter> transform_parameter = vsnode;
2605
2606
VisualShaderNodeParameterRef::ParameterType parameter_type;
2607
if (float_parameter.is_valid()) {
2608
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_FLOAT;
2609
} else if (int_parameter.is_valid()) {
2610
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_INT;
2611
} else if (uint_parameter.is_valid()) {
2612
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_UINT;
2613
} else if (boolean_parameter.is_valid()) {
2614
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_BOOLEAN;
2615
} else if (vec2_parameter.is_valid()) {
2616
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR2;
2617
} else if (vec3_parameter.is_valid()) {
2618
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR3;
2619
} else if (vec4_parameter.is_valid()) {
2620
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR4;
2621
} else if (transform_parameter.is_valid()) {
2622
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_TRANSFORM;
2623
} else if (color_parameter.is_valid()) {
2624
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_COLOR;
2625
} else {
2626
parameter_type = VisualShaderNodeParameterRef::UNIFORM_TYPE_SAMPLER;
2627
}
2628
VisualShaderNodeParameterRef::add_parameter(visual_shader->get_rid(), parameter->get_parameter_name(), parameter_type);
2629
}
2630
}
2631
}
2632
if (p_update_refs) {
2633
graph_plugin->update_parameter_refs();
2634
}
2635
}
2636
2637
void VisualShaderEditor::_update_parameter_refs(HashSet<String> &p_deleted_names) {
2638
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2639
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
2640
VisualShader::Type type = VisualShader::Type(i);
2641
2642
Vector<int> nodes = visual_shader->get_node_list(type);
2643
for (int j = 0; j < nodes.size(); j++) {
2644
if (j > 0) {
2645
Ref<VisualShaderNodeParameterRef> ref = visual_shader->get_node(type, nodes[j]);
2646
if (ref.is_valid()) {
2647
if (p_deleted_names.has(ref->get_parameter_name())) {
2648
undo_redo->add_do_method(ref.ptr(), "set_parameter_name", "[None]");
2649
undo_redo->add_undo_method(ref.ptr(), "set_parameter_name", ref->get_parameter_name());
2650
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]);
2651
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]);
2652
}
2653
}
2654
}
2655
}
2656
}
2657
}
2658
2659
void VisualShaderEditor::_update_graph() {
2660
if (visual_shader.is_null()) {
2661
return;
2662
}
2663
2664
if (!is_inside_tree()) {
2665
return;
2666
}
2667
2668
VisualShader::Type type = get_current_shader_type();
2669
2670
graph->clear_connections();
2671
// Remove all nodes.
2672
for (int i = 0; i < graph->get_child_count(); i++) {
2673
if (Object::cast_to<GraphElement>(graph->get_child(i))) {
2674
Node *node = graph->get_child(i);
2675
graph->remove_child(node);
2676
memdelete(node);
2677
i--;
2678
}
2679
}
2680
2681
List<VisualShader::Connection> node_connections;
2682
visual_shader->get_node_connections(type, &node_connections);
2683
graph_plugin->set_connections(node_connections);
2684
2685
Vector<int> nodes = visual_shader->get_node_list(type);
2686
2687
_update_parameters(false);
2688
_update_varyings();
2689
2690
graph_plugin->clear_links();
2691
graph_plugin->update_theme();
2692
2693
for (int n_i = 0; n_i < nodes.size(); n_i++) {
2694
// Update frame related stuff later since we need to have all nodes in the graph.
2695
graph_plugin->add_node(type, nodes[n_i], false, false);
2696
}
2697
2698
for (const VisualShader::Connection &E : node_connections) {
2699
int from = E.from_node;
2700
int from_idx = E.from_port;
2701
int to = E.to_node;
2702
int to_idx = E.to_port;
2703
2704
graph->connect_node(itos(from), from_idx, itos(to), to_idx);
2705
}
2706
2707
// Attach nodes to frames.
2708
for (int node_id : nodes) {
2709
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
2710
ERR_CONTINUE_MSG(vsnode.is_null(), "Node is null.");
2711
2712
if (vsnode->get_frame() != -1) {
2713
int frame_name = vsnode->get_frame();
2714
graph->attach_graph_element_to_frame(itos(node_id), itos(frame_name));
2715
}
2716
}
2717
2718
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
2719
graph->set_minimap_opacity(graph_minimap_opacity);
2720
float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature");
2721
graph->set_connection_lines_curvature(graph_lines_curvature);
2722
}
2723
2724
void VisualShaderEditor::_restore_editor_state() {
2725
const String id_string = _get_cache_id_string();
2726
2727
const String offset_cache_key = _get_cache_key("offset");
2728
const String zoom_cache_key = _get_cache_key("zoom");
2729
const Vector2 saved_scroll_offset = vs_editor_cache->get_value(id_string, offset_cache_key, Vector2());
2730
const real_t saved_zoom = vs_editor_cache->get_value(id_string, zoom_cache_key, 1.0);
2731
2732
// Setting the scroll offset needs to be further deferred because it requires min/max scroll offset to be final (as it gets clamped).
2733
callable_mp(graph, &GraphEdit::set_zoom).call_deferred(saved_zoom);
2734
callable_mp(graph, &GraphEdit::set_scroll_offset).call_deferred(saved_scroll_offset);
2735
2736
shader_fully_loaded = true;
2737
}
2738
2739
String VisualShaderEditor::_get_cache_id_string() const {
2740
String id_string = visual_shader->get_path();
2741
const ResourceUID::ID uid = EditorFileSystem::get_singleton()->get_file_uid(id_string);
2742
if (uid != ResourceUID::INVALID_ID) {
2743
id_string = ResourceUID::get_singleton()->id_to_text(uid);
2744
}
2745
return id_string;
2746
}
2747
2748
String VisualShaderEditor::_get_cache_key(const String &p_prop_name) const {
2749
const int type = get_current_shader_type();
2750
return "type" + itos(type) + ":" + p_prop_name;
2751
}
2752
2753
void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type, const String &p_name) {
2754
VisualShader::Type type = get_current_shader_type();
2755
Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
2756
if (node.is_null()) {
2757
return;
2758
}
2759
2760
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2761
undo_redo->create_action(TTR("Add Input Port"));
2762
undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
2763
undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
2764
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2765
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2766
undo_redo->commit_action();
2767
}
2768
2769
void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_type, const String &p_name) {
2770
VisualShader::Type type = get_current_shader_type();
2771
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2772
if (node.is_null()) {
2773
return;
2774
}
2775
2776
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2777
undo_redo->create_action(TTR("Add Output Port"));
2778
undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
2779
undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
2780
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2781
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2782
undo_redo->commit_action();
2783
}
2784
2785
void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_port) {
2786
VisualShader::Type type = get_current_shader_type();
2787
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2788
if (node.is_null()) {
2789
return;
2790
}
2791
2792
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2793
undo_redo->create_action(TTR("Change Input Port Type"));
2794
undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
2795
undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
2796
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2797
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2798
undo_redo->commit_action();
2799
}
2800
2801
void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_port) {
2802
VisualShader::Type type = get_current_shader_type();
2803
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2804
if (node.is_null()) {
2805
return;
2806
}
2807
2808
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2809
undo_redo->create_action(TTR("Change Output Port Type"));
2810
undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
2811
undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
2812
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2813
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2814
undo_redo->commit_action();
2815
}
2816
2817
void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *p_line_edit, int p_node_id, int p_port_id) {
2818
VisualShader::Type type = get_current_shader_type();
2819
2820
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
2821
ERR_FAIL_COND(node.is_null());
2822
2823
String prev_name = node->get_input_port_name(p_port_id);
2824
if (prev_name == p_text) {
2825
return;
2826
}
2827
2828
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
2829
ERR_FAIL_NULL(line_edit);
2830
2831
String validated_name = visual_shader->validate_port_name(p_text, node.ptr(), p_port_id, false);
2832
if (validated_name.is_empty() || prev_name == validated_name) {
2833
line_edit->set_text(node->get_input_port_name(p_port_id));
2834
return;
2835
}
2836
2837
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2838
undo_redo->create_action(TTR("Change Input Port Name"));
2839
undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, validated_name);
2840
undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
2841
undo_redo->commit_action();
2842
}
2843
2844
void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *p_line_edit, int p_node_id, int p_port_id) {
2845
VisualShader::Type type = get_current_shader_type();
2846
2847
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
2848
ERR_FAIL_COND(node.is_null());
2849
2850
String prev_name = node->get_output_port_name(p_port_id);
2851
if (prev_name == p_text) {
2852
return;
2853
}
2854
2855
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
2856
ERR_FAIL_NULL(line_edit);
2857
2858
String validated_name = visual_shader->validate_port_name(p_text, node.ptr(), p_port_id, true);
2859
if (validated_name.is_empty() || prev_name == validated_name) {
2860
line_edit->set_text(node->get_output_port_name(p_port_id));
2861
return;
2862
}
2863
2864
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2865
undo_redo->create_action(TTR("Change Output Port Name"));
2866
undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, validated_name);
2867
undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, prev_name);
2868
undo_redo->commit_action();
2869
}
2870
2871
void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expand) {
2872
VisualShader::Type type = get_current_shader_type();
2873
2874
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
2875
ERR_FAIL_COND(node.is_null());
2876
2877
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2878
if (p_expand) {
2879
undo_redo->create_action(TTR("Expand Output Port"));
2880
} else {
2881
undo_redo->create_action(TTR("Shrink Output Port"));
2882
}
2883
2884
undo_redo->add_do_method(node.ptr(), "_set_output_port_expanded", p_port, p_expand);
2885
undo_redo->add_undo_method(node.ptr(), "_set_output_port_expanded", p_port, !p_expand);
2886
2887
int type_size = 0;
2888
switch (node->get_output_port_type(p_port)) {
2889
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
2890
type_size = 2;
2891
} break;
2892
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
2893
type_size = 3;
2894
} break;
2895
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
2896
type_size = 4;
2897
} break;
2898
default:
2899
break;
2900
}
2901
2902
List<VisualShader::Connection> conns;
2903
visual_shader->get_node_connections(type, &conns);
2904
2905
for (const VisualShader::Connection &E : conns) {
2906
int cn_from_node = E.from_node;
2907
int cn_from_port = E.from_port;
2908
int cn_to_node = E.to_node;
2909
int cn_to_port = E.to_port;
2910
2911
if (cn_from_node == p_node) {
2912
if (p_expand) {
2913
if (cn_from_port > p_port) { // reconnect ports after expanded ports
2914
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2915
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2916
2917
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2918
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2919
2920
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port + type_size, cn_to_node, cn_to_port);
2921
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port + type_size, cn_to_node, cn_to_port);
2922
2923
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port + type_size, cn_to_node, cn_to_port);
2924
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port + type_size, cn_to_node, cn_to_port);
2925
}
2926
} else {
2927
if (cn_from_port > p_port + type_size) { // reconnect ports after expanded ports
2928
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2929
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2930
2931
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2932
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2933
2934
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, cn_from_node, cn_from_port - type_size, cn_to_node, cn_to_port);
2935
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - type_size, cn_to_node, cn_to_port);
2936
2937
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port - type_size, cn_to_node, cn_to_port);
2938
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - type_size, cn_to_node, cn_to_port);
2939
} else if (cn_from_port > p_port) { // disconnect component ports
2940
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2941
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2942
2943
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2944
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2945
}
2946
}
2947
}
2948
}
2949
2950
int preview_port = node->get_output_port_for_preview();
2951
if (p_expand) {
2952
if (preview_port > p_port) {
2953
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port + type_size);
2954
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
2955
}
2956
} else {
2957
if (preview_port > p_port + type_size) {
2958
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - type_size);
2959
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
2960
}
2961
}
2962
2963
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2964
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2965
undo_redo->commit_action();
2966
}
2967
2968
void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
2969
VisualShader::Type type = get_current_shader_type();
2970
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2971
if (node.is_null()) {
2972
return;
2973
}
2974
2975
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2976
undo_redo->create_action(TTR("Remove Input Port"));
2977
2978
List<VisualShader::Connection> conns;
2979
visual_shader->get_node_connections(type, &conns);
2980
for (const VisualShader::Connection &E : conns) {
2981
int cn_from_node = E.from_node;
2982
int cn_from_port = E.from_port;
2983
int cn_to_node = E.to_node;
2984
int cn_to_port = E.to_port;
2985
2986
if (cn_to_node == p_node) {
2987
if (cn_to_port == p_port) {
2988
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2989
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2990
2991
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2992
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2993
} else if (cn_to_port > p_port) {
2994
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2995
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2996
2997
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2998
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2999
3000
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
3001
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
3002
3003
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
3004
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
3005
}
3006
}
3007
}
3008
3009
undo_redo->add_do_method(node.ptr(), "remove_input_port", p_port);
3010
undo_redo->add_undo_method(node.ptr(), "add_input_port", p_port, (int)node->get_input_port_type(p_port), node->get_input_port_name(p_port));
3011
3012
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
3013
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
3014
3015
undo_redo->commit_action();
3016
}
3017
3018
void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
3019
VisualShader::Type type = get_current_shader_type();
3020
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
3021
if (node.is_null()) {
3022
return;
3023
}
3024
3025
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3026
undo_redo->create_action(TTR("Remove Output Port"));
3027
3028
List<VisualShader::Connection> conns;
3029
visual_shader->get_node_connections(type, &conns);
3030
for (const VisualShader::Connection &E : conns) {
3031
int cn_from_node = E.from_node;
3032
int cn_from_port = E.from_port;
3033
int cn_to_node = E.to_node;
3034
int cn_to_port = E.to_port;
3035
3036
if (cn_from_node == p_node) {
3037
if (cn_from_port == p_port) {
3038
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3039
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3040
3041
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3042
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3043
} else if (cn_from_port > p_port) {
3044
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3045
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3046
3047
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3048
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3049
3050
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3051
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3052
3053
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3054
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3055
}
3056
}
3057
}
3058
3059
int preview_port = node->get_output_port_for_preview();
3060
if (preview_port != -1) {
3061
if (preview_port == p_port) {
3062
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", -1);
3063
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
3064
} else if (preview_port > p_port) {
3065
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - 1);
3066
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
3067
}
3068
}
3069
3070
undo_redo->add_do_method(node.ptr(), "remove_output_port", p_port);
3071
undo_redo->add_undo_method(node.ptr(), "add_output_port", p_port, (int)node->get_output_port_type(p_port), node->get_output_port_name(p_port));
3072
3073
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
3074
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
3075
3076
undo_redo->commit_action();
3077
}
3078
3079
void VisualShaderEditor::_expression_focus_out(Object *p_code_edit, int p_node) {
3080
VisualShader::Type type = get_current_shader_type();
3081
Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
3082
if (node.is_null()) {
3083
return;
3084
}
3085
3086
CodeEdit *expression_box = Object::cast_to<CodeEdit>(p_code_edit);
3087
3088
if (node->get_expression() == expression_box->get_text()) {
3089
return;
3090
}
3091
3092
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3093
undo_redo->create_action(TTR("Set VisualShader Expression"));
3094
undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
3095
undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
3096
undo_redo->add_do_method(graph_plugin.ptr(), "set_expression", type, p_node, expression_box->get_text());
3097
undo_redo->add_undo_method(graph_plugin.ptr(), "set_expression", type, p_node, node->get_expression());
3098
undo_redo->commit_action();
3099
}
3100
3101
void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) {
3102
VisualShader::Type type = VisualShader::Type(p_type);
3103
Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(type, p_node);
3104
if (node.is_null()) {
3105
return;
3106
}
3107
3108
Size2 size = p_size;
3109
if (!node->is_allow_v_resize()) {
3110
size.y = 0;
3111
}
3112
3113
node->set_size(size);
3114
3115
if (get_current_shader_type() == type) {
3116
Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
3117
Control *text_box = nullptr;
3118
if (expression_node.is_valid()) {
3119
text_box = expression_node->is_ctrl_pressed(0);
3120
if (text_box) {
3121
text_box->set_custom_minimum_size(Size2(0, 0));
3122
}
3123
}
3124
3125
GraphElement *graph_element = nullptr;
3126
Node *node2 = graph->get_node(itos(p_node));
3127
graph_element = Object::cast_to<GraphElement>(node2);
3128
if (!graph_element) {
3129
return;
3130
}
3131
3132
graph_element->set_size(size);
3133
}
3134
3135
// Update all parent frames.
3136
graph_plugin->update_frames(type, p_node);
3137
}
3138
3139
// Called once after the node was resized.
3140
void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) {
3141
Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(VisualShader::Type(p_type), p_node);
3142
if (node.is_null()) {
3143
return;
3144
}
3145
3146
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_node(itos(p_node)));
3147
if (!graph_element) {
3148
return;
3149
}
3150
3151
Size2 size = graph_element->get_size();
3152
3153
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3154
undo_redo->create_action(TTR("Resize VisualShader Node"));
3155
undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, size);
3156
undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
3157
undo_redo->commit_action();
3158
}
3159
3160
void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
3161
VisualShader::Type type = get_current_shader_type();
3162
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
3163
if (node.is_null()) {
3164
return;
3165
}
3166
int prev_port = node->get_output_port_for_preview();
3167
if (node->get_output_port_for_preview() == p_port) {
3168
p_port = -1; //toggle it
3169
}
3170
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3171
undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview"));
3172
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port);
3173
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port);
3174
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, p_node);
3175
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, p_node);
3176
undo_redo->commit_action();
3177
}
3178
3179
void VisualShaderEditor::_frame_title_popup_show(const Point2 &p_position, int p_node_id) {
3180
VisualShader::Type type = get_current_shader_type();
3181
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3182
if (node.is_null()) {
3183
return;
3184
}
3185
frame_title_change_edit->set_text(node->get_title());
3186
frame_title_change_popup->set_meta("id", p_node_id);
3187
frame_title_change_popup->set_position(p_position);
3188
frame_title_change_popup->popup();
3189
3190
// Select current text.
3191
frame_title_change_edit->grab_focus();
3192
}
3193
3194
void VisualShaderEditor::_frame_title_text_changed(const String &p_new_text) {
3195
frame_title_change_edit->reset_size();
3196
frame_title_change_popup->reset_size();
3197
}
3198
3199
void VisualShaderEditor::_frame_title_text_submitted(const String &p_new_text) {
3200
frame_title_change_popup->hide();
3201
}
3202
3203
void VisualShaderEditor::_frame_title_popup_focus_out() {
3204
frame_title_change_popup->hide();
3205
}
3206
3207
void VisualShaderEditor::_frame_title_popup_hide() {
3208
int node_id = (int)frame_title_change_popup->get_meta("id", -1);
3209
ERR_FAIL_COND(node_id == -1);
3210
3211
VisualShader::Type type = get_current_shader_type();
3212
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3213
3214
ERR_FAIL_COND(node.is_null());
3215
3216
if (node->get_title() == frame_title_change_edit->get_text()) {
3217
return; // nothing changed - ignored
3218
}
3219
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3220
undo_redo->create_action(TTR("Set Frame Title"));
3221
undo_redo->add_do_method(node.ptr(), "set_title", frame_title_change_edit->get_text());
3222
undo_redo->add_undo_method(node.ptr(), "set_title", node->get_title());
3223
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, node_id);
3224
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, node_id);
3225
undo_redo->commit_action();
3226
}
3227
3228
void VisualShaderEditor::_frame_color_enabled_changed(int p_node_id) {
3229
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
3230
3231
// The new state.
3232
bool tint_color_enabled = !popup_menu->is_item_checked(item_index);
3233
3234
popup_menu->set_item_checked(item_index, tint_color_enabled);
3235
int frame_color_item_idx = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_COLOR);
3236
if (tint_color_enabled && frame_color_item_idx == -1) {
3237
popup_menu->add_item(TTR("Set Tint Color"), NodeMenuOptions::SET_FRAME_COLOR);
3238
} else if (!tint_color_enabled && frame_color_item_idx != -1) {
3239
popup_menu->remove_item(frame_color_item_idx);
3240
}
3241
3242
VisualShader::Type type = get_current_shader_type();
3243
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3244
3245
ERR_FAIL_COND(node.is_null());
3246
3247
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3248
undo_redo->create_action(TTR("Toggle Frame Color"));
3249
undo_redo->add_do_method(node.ptr(), "set_tint_color_enabled", tint_color_enabled);
3250
undo_redo->add_undo_method(node.ptr(), "set_tint_color_enabled", node->is_tint_color_enabled());
3251
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_color_enabled", (int)type, p_node_id, tint_color_enabled);
3252
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_color_enabled", (int)type, p_node_id, node->is_tint_color_enabled());
3253
undo_redo->commit_action();
3254
}
3255
3256
void VisualShaderEditor::_frame_color_popup_show(const Point2 &p_position, int p_node_id) {
3257
VisualShader::Type type = get_current_shader_type();
3258
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3259
if (node.is_null()) {
3260
return;
3261
}
3262
frame_tint_color_picker->set_pick_color(node->get_tint_color());
3263
frame_tint_color_pick_popup->set_meta("id", p_node_id);
3264
frame_tint_color_pick_popup->set_position(p_position);
3265
frame_tint_color_pick_popup->popup();
3266
}
3267
3268
void VisualShaderEditor::_frame_color_confirm() {
3269
frame_tint_color_pick_popup->hide();
3270
}
3271
3272
void VisualShaderEditor::_frame_color_changed(const Color &p_color) {
3273
ERR_FAIL_COND(!frame_tint_color_pick_popup->has_meta("id"));
3274
int node_id = (int)frame_tint_color_pick_popup->get_meta("id");
3275
3276
VisualShader::Type type = get_current_shader_type();
3277
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3278
ERR_FAIL_COND(node.is_null());
3279
node->set_tint_color(p_color);
3280
graph_plugin->set_frame_color(type, node_id, p_color);
3281
}
3282
3283
void VisualShaderEditor::_frame_color_popup_hide() {
3284
ERR_FAIL_COND(!frame_tint_color_pick_popup->has_meta("id"));
3285
int node_id = (int)frame_tint_color_pick_popup->get_meta("id");
3286
3287
VisualShader::Type type = get_current_shader_type();
3288
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3289
ERR_FAIL_COND(node.is_null());
3290
3291
if (node->get_tint_color() == frame_tint_color_picker->get_pick_color()) {
3292
return;
3293
}
3294
3295
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3296
undo_redo->create_action(TTR("Set Frame Color"));
3297
undo_redo->add_do_method(node.ptr(), "set_tint_color", frame_tint_color_picker->get_pick_color());
3298
undo_redo->add_undo_method(node.ptr(), "set_tint_color", node->get_tint_color());
3299
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_color", (int)type, node_id, frame_tint_color_picker->get_pick_color());
3300
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_color", (int)type, node_id, node->get_tint_color());
3301
undo_redo->commit_action();
3302
}
3303
3304
void VisualShaderEditor::_frame_autoshrink_enabled_changed(int p_node_id) {
3305
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
3306
3307
bool autoshrink_enabled = popup_menu->is_item_checked(item_index);
3308
3309
popup_menu->set_item_checked(item_index, !autoshrink_enabled);
3310
3311
VisualShader::Type type = get_current_shader_type();
3312
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3313
3314
ERR_FAIL_COND(node.is_null());
3315
3316
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3317
undo_redo->create_action(TTR("Toggle Auto Shrink"));
3318
undo_redo->add_do_method(node.ptr(), "set_autoshrink_enabled", !autoshrink_enabled);
3319
undo_redo->add_undo_method(node.ptr(), "set_autoshrink_enabled", autoshrink_enabled);
3320
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_autoshrink_enabled", (int)type, p_node_id, !autoshrink_enabled);
3321
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_autoshrink_enabled", (int)type, p_node_id, autoshrink_enabled);
3322
undo_redo->commit_action();
3323
3324
popup_menu->hide();
3325
}
3326
3327
void VisualShaderEditor::_parameter_line_edit_changed(const String &p_text, int p_node_id) {
3328
VisualShader::Type type = get_current_shader_type();
3329
3330
Ref<VisualShaderNodeParameter> node = visual_shader->get_node(type, p_node_id);
3331
ERR_FAIL_COND(node.is_null());
3332
3333
String validated_name = visual_shader->validate_parameter_name(p_text, node);
3334
3335
if (validated_name == node->get_parameter_name()) {
3336
return;
3337
}
3338
3339
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3340
undo_redo->create_action(TTR("Set Parameter Name"));
3341
undo_redo->add_do_method(node.ptr(), "set_parameter_name", validated_name);
3342
undo_redo->add_undo_method(node.ptr(), "set_parameter_name", node->get_parameter_name());
3343
undo_redo->add_do_method(graph_plugin.ptr(), "set_parameter_name", type, p_node_id, validated_name);
3344
undo_redo->add_undo_method(graph_plugin.ptr(), "set_parameter_name", type, p_node_id, node->get_parameter_name());
3345
undo_redo->add_do_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id);
3346
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id);
3347
3348
undo_redo->add_do_method(this, "_update_parameters", true);
3349
undo_redo->add_undo_method(this, "_update_parameters", true);
3350
3351
HashSet<String> changed_names;
3352
changed_names.insert(node->get_parameter_name());
3353
_update_parameter_refs(changed_names);
3354
3355
undo_redo->commit_action();
3356
}
3357
3358
void VisualShaderEditor::_parameter_line_edit_focus_out(Object *line_edit, int p_node_id) {
3359
_parameter_line_edit_changed(Object::cast_to<LineEdit>(line_edit)->get_text(), p_node_id);
3360
}
3361
3362
void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) {
3363
if (!p_output) {
3364
_change_input_port_name(Object::cast_to<LineEdit>(line_edit)->get_text(), line_edit, p_node_id, p_port_id);
3365
} else {
3366
_change_output_port_name(Object::cast_to<LineEdit>(line_edit)->get_text(), line_edit, p_node_id, p_port_id);
3367
}
3368
}
3369
3370
void VisualShaderEditor::_port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
3371
VisualShader::Type type = get_current_shader_type();
3372
Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node);
3373
ERR_FAIL_COND(vsn.is_null());
3374
3375
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3376
undo_redo->create_action(TTR("Set Input Default Port"));
3377
3378
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr());
3379
if (custom.is_valid()) {
3380
undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, p_value);
3381
undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
3382
} else {
3383
undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, p_value);
3384
undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
3385
}
3386
undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, p_value);
3387
undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port));
3388
undo_redo->commit_action();
3389
}
3390
3391
void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) {
3392
VisualShader::Type type = get_current_shader_type();
3393
Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, p_node);
3394
Variant value = vs_node->get_input_port_default_value(p_port);
3395
3396
edited_property_holder->set_edited_property(value);
3397
editing_node = p_node;
3398
editing_port = p_port;
3399
3400
if (property_editor) {
3401
property_editor->disconnect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
3402
property_editor_popup->remove_child(property_editor);
3403
}
3404
3405
// TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget.
3406
property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE, true);
3407
ERR_FAIL_NULL_MSG(property_editor, "Failed to create property editor for type: " + Variant::get_type_name(value.get_type()));
3408
3409
// Determine the best size for the popup based on the property type.
3410
// This is done here, since the property editors are also used in the inspector where they have different layout requirements, so we can't just change their default minimum size.
3411
Size2 popup_pref_size;
3412
switch (value.get_type()) {
3413
case Variant::VECTOR3:
3414
case Variant::BASIS:
3415
popup_pref_size.width = 320;
3416
break;
3417
case Variant::VECTOR4:
3418
case Variant::PLANE:
3419
case Variant::TRANSFORM2D:
3420
case Variant::TRANSFORM3D:
3421
case Variant::PROJECTION:
3422
popup_pref_size.width = 480;
3423
break;
3424
default:
3425
popup_pref_size.width = 180;
3426
break;
3427
}
3428
property_editor_popup->set_min_size(popup_pref_size * EDSCALE);
3429
3430
property_editor->set_object_and_property(edited_property_holder.ptr(), "edited_property");
3431
property_editor->update_property();
3432
property_editor->set_name_split_ratio(0);
3433
property_editor_popup->add_child(property_editor);
3434
3435
property_editor->connect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
3436
3437
Button *button = Object::cast_to<Button>(p_button);
3438
if (button) {
3439
property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom());
3440
}
3441
property_editor_popup->reset_size();
3442
if (button) {
3443
property_editor_popup->popup();
3444
} else {
3445
property_editor_popup->popup_centered_ratio();
3446
}
3447
property_editor->select(0); // Focus the first focusable control.
3448
}
3449
3450
void VisualShaderEditor::_set_custom_node_option(int p_index, int p_node, int p_op) {
3451
VisualShader::Type type = get_current_shader_type();
3452
Ref<VisualShaderNodeCustom> node = visual_shader->get_node(type, p_node);
3453
if (node.is_null()) {
3454
return;
3455
}
3456
3457
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3458
undo_redo->create_action(TTR("Set Custom Node Option"));
3459
undo_redo->add_do_method(node.ptr(), "_set_option_index", p_op, p_index);
3460
undo_redo->add_undo_method(node.ptr(), "_set_option_index", p_op, node->get_option_index(p_op));
3461
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
3462
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
3463
undo_redo->commit_action();
3464
}
3465
3466
void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Variant> &p_ops) {
3467
// INPUT
3468
{
3469
VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(p_node);
3470
3471
if (input) {
3472
ERR_FAIL_COND(!p_ops[0].is_string());
3473
input->set_input_name((String)p_ops[0]);
3474
return;
3475
}
3476
}
3477
3478
// FLOAT_CONST
3479
{
3480
VisualShaderNodeFloatConstant *float_const = Object::cast_to<VisualShaderNodeFloatConstant>(p_node);
3481
3482
if (float_const) {
3483
ERR_FAIL_COND(p_ops[0].get_type() != Variant::FLOAT);
3484
float_const->set_constant((float)p_ops[0]);
3485
return;
3486
}
3487
}
3488
3489
// FLOAT_OP
3490
{
3491
VisualShaderNodeFloatOp *float_op = Object::cast_to<VisualShaderNodeFloatOp>(p_node);
3492
3493
if (float_op) {
3494
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3495
float_op->set_operator((VisualShaderNodeFloatOp::Operator)(int)p_ops[0]);
3496
return;
3497
}
3498
}
3499
3500
// FLOAT_FUNC
3501
{
3502
VisualShaderNodeFloatFunc *float_func = Object::cast_to<VisualShaderNodeFloatFunc>(p_node);
3503
3504
if (float_func) {
3505
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3506
float_func->set_function((VisualShaderNodeFloatFunc::Function)(int)p_ops[0]);
3507
return;
3508
}
3509
}
3510
3511
// VECTOR_OP
3512
{
3513
VisualShaderNodeVectorOp *vec_op = Object::cast_to<VisualShaderNodeVectorOp>(p_node);
3514
3515
if (vec_op) {
3516
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3517
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3518
vec_op->set_operator((VisualShaderNodeVectorOp::Operator)(int)p_ops[0]);
3519
vec_op->set_op_type((VisualShaderNodeVectorOp::OpType)(int)p_ops[1]);
3520
return;
3521
}
3522
}
3523
3524
// VECTOR_FUNC
3525
{
3526
VisualShaderNodeVectorFunc *vec_func = Object::cast_to<VisualShaderNodeVectorFunc>(p_node);
3527
3528
if (vec_func) {
3529
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3530
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3531
vec_func->set_function((VisualShaderNodeVectorFunc::Function)(int)p_ops[0]);
3532
vec_func->set_op_type((VisualShaderNodeVectorFunc::OpType)(int)p_ops[1]);
3533
return;
3534
}
3535
}
3536
3537
// COLOR_OP
3538
{
3539
VisualShaderNodeColorOp *color_op = Object::cast_to<VisualShaderNodeColorOp>(p_node);
3540
3541
if (color_op) {
3542
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3543
color_op->set_operator((VisualShaderNodeColorOp::Operator)(int)p_ops[0]);
3544
return;
3545
}
3546
}
3547
3548
// COLOR_FUNC
3549
{
3550
VisualShaderNodeColorFunc *color_func = Object::cast_to<VisualShaderNodeColorFunc>(p_node);
3551
3552
if (color_func) {
3553
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3554
color_func->set_function((VisualShaderNodeColorFunc::Function)(int)p_ops[0]);
3555
return;
3556
}
3557
}
3558
3559
// INT_OP
3560
{
3561
VisualShaderNodeIntOp *int_op = Object::cast_to<VisualShaderNodeIntOp>(p_node);
3562
3563
if (int_op) {
3564
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3565
int_op->set_operator((VisualShaderNodeIntOp::Operator)(int)p_ops[0]);
3566
return;
3567
}
3568
}
3569
3570
// INT_FUNC
3571
{
3572
VisualShaderNodeIntFunc *int_func = Object::cast_to<VisualShaderNodeIntFunc>(p_node);
3573
3574
if (int_func) {
3575
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3576
int_func->set_function((VisualShaderNodeIntFunc::Function)(int)p_ops[0]);
3577
return;
3578
}
3579
}
3580
3581
// UINT_OP
3582
{
3583
VisualShaderNodeUIntOp *uint_op = Object::cast_to<VisualShaderNodeUIntOp>(p_node);
3584
3585
if (uint_op) {
3586
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3587
uint_op->set_operator((VisualShaderNodeUIntOp::Operator)(int)p_ops[0]);
3588
return;
3589
}
3590
}
3591
3592
// UINT_FUNC
3593
{
3594
VisualShaderNodeUIntFunc *uint_func = Object::cast_to<VisualShaderNodeUIntFunc>(p_node);
3595
3596
if (uint_func) {
3597
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3598
uint_func->set_function((VisualShaderNodeUIntFunc::Function)(int)p_ops[0]);
3599
return;
3600
}
3601
}
3602
3603
// TRANSFORM_OP
3604
{
3605
VisualShaderNodeTransformOp *mat_op = Object::cast_to<VisualShaderNodeTransformOp>(p_node);
3606
3607
if (mat_op) {
3608
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3609
mat_op->set_operator((VisualShaderNodeTransformOp::Operator)(int)p_ops[0]);
3610
return;
3611
}
3612
}
3613
3614
// TRANSFORM_FUNC
3615
{
3616
VisualShaderNodeTransformFunc *mat_func = Object::cast_to<VisualShaderNodeTransformFunc>(p_node);
3617
3618
if (mat_func) {
3619
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3620
mat_func->set_function((VisualShaderNodeTransformFunc::Function)(int)p_ops[0]);
3621
return;
3622
}
3623
}
3624
3625
// VECTOR_COMPOSE
3626
{
3627
VisualShaderNodeVectorCompose *vec_compose = Object::cast_to<VisualShaderNodeVectorCompose>(p_node);
3628
3629
if (vec_compose) {
3630
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3631
vec_compose->set_op_type((VisualShaderNodeVectorCompose::OpType)(int)p_ops[0]);
3632
return;
3633
}
3634
}
3635
3636
// VECTOR_DECOMPOSE
3637
{
3638
VisualShaderNodeVectorDecompose *vec_decompose = Object::cast_to<VisualShaderNodeVectorDecompose>(p_node);
3639
3640
if (vec_decompose) {
3641
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3642
vec_decompose->set_op_type((VisualShaderNodeVectorDecompose::OpType)(int)p_ops[0]);
3643
return;
3644
}
3645
}
3646
3647
// UV_FUNC
3648
{
3649
VisualShaderNodeUVFunc *uv_func = Object::cast_to<VisualShaderNodeUVFunc>(p_node);
3650
3651
if (uv_func) {
3652
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3653
uv_func->set_function((VisualShaderNodeUVFunc::Function)(int)p_ops[0]);
3654
return;
3655
}
3656
}
3657
3658
// IS
3659
{
3660
VisualShaderNodeIs *is = Object::cast_to<VisualShaderNodeIs>(p_node);
3661
3662
if (is) {
3663
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3664
is->set_function((VisualShaderNodeIs::Function)(int)p_ops[0]);
3665
return;
3666
}
3667
}
3668
3669
// COMPARE
3670
{
3671
VisualShaderNodeCompare *cmp = Object::cast_to<VisualShaderNodeCompare>(p_node);
3672
3673
if (cmp) {
3674
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3675
cmp->set_function((VisualShaderNodeCompare::Function)(int)p_ops[0]);
3676
return;
3677
}
3678
}
3679
3680
// DISTANCE
3681
{
3682
VisualShaderNodeVectorDistance *dist = Object::cast_to<VisualShaderNodeVectorDistance>(p_node);
3683
3684
if (dist) {
3685
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3686
dist->set_op_type((VisualShaderNodeVectorDistance::OpType)(int)p_ops[0]);
3687
return;
3688
}
3689
}
3690
3691
// DERIVATIVE
3692
{
3693
VisualShaderNodeDerivativeFunc *der_func = Object::cast_to<VisualShaderNodeDerivativeFunc>(p_node);
3694
3695
if (der_func) {
3696
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3697
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3698
der_func->set_function((VisualShaderNodeDerivativeFunc::Function)(int)p_ops[0]);
3699
der_func->set_op_type((VisualShaderNodeDerivativeFunc::OpType)(int)p_ops[1]);
3700
return;
3701
}
3702
}
3703
3704
// MIX
3705
{
3706
VisualShaderNodeMix *mix = Object::cast_to<VisualShaderNodeMix>(p_node);
3707
3708
if (mix) {
3709
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3710
mix->set_op_type((VisualShaderNodeMix::OpType)(int)p_ops[0]);
3711
return;
3712
}
3713
}
3714
3715
// CLAMP
3716
{
3717
VisualShaderNodeClamp *clamp_func = Object::cast_to<VisualShaderNodeClamp>(p_node);
3718
3719
if (clamp_func) {
3720
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3721
clamp_func->set_op_type((VisualShaderNodeClamp::OpType)(int)p_ops[0]);
3722
return;
3723
}
3724
}
3725
3726
// SWITCH
3727
{
3728
VisualShaderNodeSwitch *switch_func = Object::cast_to<VisualShaderNodeSwitch>(p_node);
3729
3730
if (switch_func) {
3731
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3732
switch_func->set_op_type((VisualShaderNodeSwitch::OpType)(int)p_ops[0]);
3733
return;
3734
}
3735
}
3736
3737
// FACEFORWARD
3738
{
3739
VisualShaderNodeFaceForward *face_forward = Object::cast_to<VisualShaderNodeFaceForward>(p_node);
3740
if (face_forward) {
3741
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3742
face_forward->set_op_type((VisualShaderNodeFaceForward::OpType)(int)p_ops[0]);
3743
return;
3744
}
3745
}
3746
3747
// LENGTH
3748
{
3749
VisualShaderNodeVectorLen *length = Object::cast_to<VisualShaderNodeVectorLen>(p_node);
3750
if (length) {
3751
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3752
length->set_op_type((VisualShaderNodeVectorLen::OpType)(int)p_ops[0]);
3753
return;
3754
}
3755
}
3756
3757
// SMOOTHSTEP
3758
{
3759
VisualShaderNodeSmoothStep *smooth_step_func = Object::cast_to<VisualShaderNodeSmoothStep>(p_node);
3760
3761
if (smooth_step_func) {
3762
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3763
smooth_step_func->set_op_type((VisualShaderNodeSmoothStep::OpType)(int)p_ops[0]);
3764
return;
3765
}
3766
}
3767
3768
// STEP
3769
{
3770
VisualShaderNodeStep *step_func = Object::cast_to<VisualShaderNodeStep>(p_node);
3771
3772
if (step_func) {
3773
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3774
step_func->set_op_type((VisualShaderNodeStep::OpType)(int)p_ops[0]);
3775
return;
3776
}
3777
}
3778
3779
// MULTIPLY_ADD
3780
{
3781
VisualShaderNodeMultiplyAdd *fma_func = Object::cast_to<VisualShaderNodeMultiplyAdd>(p_node);
3782
3783
if (fma_func) {
3784
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3785
fma_func->set_op_type((VisualShaderNodeMultiplyAdd::OpType)(int)p_ops[0]);
3786
}
3787
}
3788
3789
// REMAP
3790
{
3791
VisualShaderNodeRemap *remap_func = Object::cast_to<VisualShaderNodeRemap>(p_node);
3792
3793
if (remap_func) {
3794
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3795
remap_func->set_op_type((VisualShaderNodeRemap::OpType)(int)p_ops[0]);
3796
}
3797
}
3798
3799
// REFRACT
3800
{
3801
VisualShaderNodeVectorRefract *refract = Object::cast_to<VisualShaderNodeVectorRefract>(p_node);
3802
3803
if (refract) {
3804
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3805
refract->set_op_type((VisualShaderNodeVectorRefract::OpType)(int)p_ops[0]);
3806
return;
3807
}
3808
}
3809
}
3810
3811
void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, const String &p_resource_path, int p_node_idx) {
3812
ERR_FAIL_INDEX(p_idx, add_options.size());
3813
3814
VisualShader::Type type = get_current_shader_type();
3815
3816
Ref<VisualShaderNode> vsnode;
3817
3818
bool is_custom = add_options[p_idx].is_custom;
3819
3820
if (!is_custom && !add_options[p_idx].type.is_empty()) {
3821
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instantiate(add_options[p_idx].type));
3822
ERR_FAIL_NULL(vsn);
3823
if (!p_ops.is_empty()) {
3824
_setup_node(vsn, p_ops);
3825
}
3826
VisualShaderNodeParameterRef *parameter_ref = Object::cast_to<VisualShaderNodeParameterRef>(vsn);
3827
if (parameter_ref && to_node != -1 && to_slot != -1) {
3828
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
3829
bool success = false;
3830
3831
for (int i = 0; i < parameter_ref->get_parameters_count(); i++) {
3832
if (parameter_ref->get_port_type_by_index(i) == input_port_type) {
3833
parameter_ref->set_parameter_name(parameter_ref->get_parameter_name_by_index(i));
3834
success = true;
3835
break;
3836
}
3837
}
3838
if (!success) {
3839
for (int i = 0; i < parameter_ref->get_parameters_count(); i++) {
3840
if (visual_shader->is_port_types_compatible(parameter_ref->get_port_type_by_index(i), input_port_type)) {
3841
parameter_ref->set_parameter_name(parameter_ref->get_parameter_name_by_index(i));
3842
break;
3843
}
3844
}
3845
}
3846
}
3847
3848
vsnode = Ref<VisualShaderNode>(vsn);
3849
} else {
3850
StringName base_type;
3851
bool is_native = add_options[p_idx].is_native;
3852
3853
if (is_native) {
3854
base_type = add_options[p_idx].type;
3855
} else {
3856
ERR_FAIL_COND(add_options[p_idx].script.is_null());
3857
base_type = add_options[p_idx].script->get_instance_base_type();
3858
}
3859
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instantiate(base_type));
3860
ERR_FAIL_NULL(vsn);
3861
vsnode = Ref<VisualShaderNode>(vsn);
3862
if (!is_native) {
3863
vsnode->set_script(add_options[p_idx].script);
3864
}
3865
VisualShaderNodeCustom *custom_node = Object::cast_to<VisualShaderNodeCustom>(vsn);
3866
ERR_FAIL_NULL(custom_node);
3867
custom_node->update_property_default_values();
3868
custom_node->update_input_port_default_values();
3869
custom_node->update_properties();
3870
}
3871
3872
bool is_texture2d = (Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr()) != nullptr);
3873
bool is_texture3d = (Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr()) != nullptr);
3874
bool is_texture2d_array = (Object::cast_to<VisualShaderNodeTexture2DArray>(vsnode.ptr()) != nullptr);
3875
bool is_cubemap = (Object::cast_to<VisualShaderNodeCubemap>(vsnode.ptr()) != nullptr);
3876
bool is_curve = (Object::cast_to<VisualShaderNodeCurveTexture>(vsnode.ptr()) != nullptr);
3877
bool is_curve_xyz = (Object::cast_to<VisualShaderNodeCurveXYZTexture>(vsnode.ptr()) != nullptr);
3878
bool is_parameter = (Object::cast_to<VisualShaderNodeParameter>(vsnode.ptr()) != nullptr);
3879
bool is_mesh_emitter = (Object::cast_to<VisualShaderNodeParticleMeshEmitter>(vsnode.ptr()) != nullptr);
3880
3881
Point2 position = graph->get_scroll_offset();
3882
3883
if (saved_node_pos_dirty) {
3884
position += saved_node_pos;
3885
} else {
3886
position += graph->get_size() * 0.5;
3887
position /= EDSCALE;
3888
}
3889
position /= graph->get_zoom();
3890
position /= cached_theme_base_scale;
3891
saved_node_pos_dirty = false;
3892
3893
int id_to_use = visual_shader->get_valid_node_id(type);
3894
3895
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3896
if (p_resource_path.is_empty()) {
3897
undo_redo->create_action(TTR("Add Node to Visual Shader"));
3898
} else {
3899
id_to_use += p_node_idx;
3900
}
3901
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
3902
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
3903
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use, false, true);
3904
undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_to_use, false);
3905
3906
VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr());
3907
if (expr) {
3908
expr->set_size(Size2(250 * EDSCALE, 150 * EDSCALE));
3909
}
3910
3911
Ref<VisualShaderNodeFrame> frame = vsnode;
3912
if (frame.is_valid()) {
3913
frame->set_size(Size2(320 * EDSCALE, 180 * EDSCALE));
3914
}
3915
3916
Ref<VisualShaderNodeReroute> reroute = vsnode;
3917
3918
bool created_expression_port = false;
3919
3920
// A node is inserted in an already present connection.
3921
if (from_node != -1 && from_slot != -1 && to_node != -1 && to_slot != -1) {
3922
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, to_node, to_slot);
3923
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, to_node, to_slot);
3924
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, to_node, to_slot);
3925
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, to_node, to_slot);
3926
}
3927
3928
// Create a connection from the output port of an existing node to the new one.
3929
if (from_node != -1 && from_slot != -1) {
3930
VisualShaderNode::PortType output_port_type = visual_shader->get_node(type, from_node)->get_output_port_type(from_slot);
3931
3932
if (expr && expr->is_editable()) {
3933
expr->add_input_port(0, output_port_type, "input0");
3934
created_expression_port = true;
3935
}
3936
3937
if (vsnode->get_input_port_count() > 0 || created_expression_port) {
3938
int _to_node = id_to_use;
3939
3940
if (created_expression_port) {
3941
int _to_slot = 0;
3942
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3943
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3944
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3945
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3946
} else {
3947
int _to_slot = -1;
3948
3949
// Attempting to connect to the default input port or to the first correct port (if it's not found).
3950
for (int i = 0; i < vsnode->get_input_port_count(); i++) {
3951
if (visual_shader->is_port_types_compatible(output_port_type, vsnode->get_input_port_type(i)) || reroute.is_valid()) {
3952
if (i == vsnode->get_default_input_port(output_port_type)) {
3953
_to_slot = i;
3954
break;
3955
} else if (_to_slot == -1) {
3956
_to_slot = i;
3957
}
3958
}
3959
}
3960
3961
if (_to_slot >= 0) {
3962
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3963
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3964
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3965
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3966
}
3967
}
3968
3969
if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
3970
if (is_texture2d) {
3971
undo_redo->force_fixed_history(); // vsnode is freshly created and has no path, so history can't be correctly determined.
3972
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
3973
}
3974
if (is_texture3d || is_texture2d_array) {
3975
undo_redo->force_fixed_history();
3976
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
3977
}
3978
if (is_cubemap) {
3979
undo_redo->force_fixed_history();
3980
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
3981
}
3982
}
3983
}
3984
}
3985
3986
// Create a connection from the new node to an input port of an existing one.
3987
if (to_node != -1 && to_slot != -1) {
3988
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
3989
3990
if (expr && expr->is_editable() && input_port_type != VisualShaderNode::PORT_TYPE_SAMPLER) {
3991
expr->add_output_port(0, input_port_type, "output0");
3992
String initial_expression_code;
3993
3994
switch (input_port_type) {
3995
case VisualShaderNode::PORT_TYPE_SCALAR:
3996
initial_expression_code = "output0 = 1.0;";
3997
break;
3998
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
3999
initial_expression_code = "output0 = 1;";
4000
break;
4001
case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
4002
initial_expression_code = "output0 = 1u;";
4003
break;
4004
case VisualShaderNode::PORT_TYPE_VECTOR_2D:
4005
initial_expression_code = "output0 = vec2(1.0, 1.0);";
4006
break;
4007
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
4008
initial_expression_code = "output0 = vec3(1.0, 1.0, 1.0);";
4009
break;
4010
case VisualShaderNode::PORT_TYPE_VECTOR_4D:
4011
initial_expression_code = "output0 = vec4(1.0, 1.0, 1.0, 1.0);";
4012
break;
4013
case VisualShaderNode::PORT_TYPE_BOOLEAN:
4014
initial_expression_code = "output0 = true;";
4015
break;
4016
case VisualShaderNode::PORT_TYPE_TRANSFORM:
4017
initial_expression_code = "output0 = mat4(1.0);";
4018
break;
4019
default:
4020
break;
4021
}
4022
4023
expr->set_expression(initial_expression_code);
4024
expr->set_size(Size2(500 * EDSCALE, 200 * EDSCALE));
4025
created_expression_port = true;
4026
}
4027
if (vsnode->get_output_port_count() > 0 || created_expression_port) {
4028
int _from_node = id_to_use;
4029
4030
if (created_expression_port) {
4031
int _from_slot = 0;
4032
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
4033
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
4034
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
4035
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
4036
} else {
4037
// Need to setting up Input node properly before committing since `is_port_types_compatible` (calling below) is using `mode` and `shader_type`.
4038
VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsnode.ptr());
4039
if (input) {
4040
input->set_shader_mode(visual_shader->get_mode());
4041
input->set_shader_type(get_current_shader_type());
4042
}
4043
4044
// Attempting to connect to the first correct port.
4045
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
4046
if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(i), input_port_type) || reroute.is_valid()) {
4047
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
4048
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, i, to_node, to_slot);
4049
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
4050
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, i, to_node, to_slot);
4051
break;
4052
}
4053
}
4054
}
4055
}
4056
}
4057
4058
_member_cancel();
4059
4060
if (is_parameter) {
4061
undo_redo->add_do_method(this, "_update_parameters", true);
4062
undo_redo->add_undo_method(this, "_update_parameters", true);
4063
}
4064
4065
if (is_curve) {
4066
callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve).call_deferred(id_to_use);
4067
}
4068
4069
if (is_curve_xyz) {
4070
callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve_xyz).call_deferred(id_to_use);
4071
}
4072
4073
if (p_resource_path.is_empty()) {
4074
undo_redo->commit_action();
4075
} else {
4076
//post-initialization
4077
4078
if (is_texture2d || is_texture3d || is_curve || is_curve_xyz) {
4079
undo_redo->force_fixed_history();
4080
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
4081
return;
4082
}
4083
4084
if (is_cubemap) {
4085
undo_redo->force_fixed_history();
4086
undo_redo->add_do_method(vsnode.ptr(), "set_cube_map", ResourceLoader::load(p_resource_path));
4087
return;
4088
}
4089
4090
if (is_texture2d_array) {
4091
undo_redo->force_fixed_history();
4092
undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
4093
return;
4094
}
4095
4096
if (is_mesh_emitter) {
4097
undo_redo->add_do_method(vsnode.ptr(), "set_mesh", ResourceLoader::load(p_resource_path));
4098
return;
4099
}
4100
}
4101
}
4102
4103
void VisualShaderEditor::_add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) {
4104
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4105
undo_redo->create_action(vformat(TTR("Add Varying to Visual Shader: %s"), p_name));
4106
4107
undo_redo->add_do_method(visual_shader.ptr(), "add_varying", p_name, p_mode, p_type);
4108
undo_redo->add_undo_method(visual_shader.ptr(), "remove_varying", p_name);
4109
4110
undo_redo->add_do_method(this, "_update_varyings");
4111
undo_redo->add_undo_method(this, "_update_varyings");
4112
4113
for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
4114
if (p_mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
4115
continue;
4116
}
4117
4118
VisualShader::Type type = VisualShader::Type(i);
4119
Vector<int> nodes = visual_shader->get_node_list(type);
4120
4121
for (int j = 0; j < nodes.size(); j++) {
4122
int node_id = nodes[j];
4123
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
4124
Ref<VisualShaderNodeVarying> var = vsnode;
4125
4126
if (var.is_valid()) {
4127
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
4128
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
4129
}
4130
}
4131
}
4132
4133
undo_redo->add_do_method(this, "_update_varying_tree");
4134
undo_redo->add_undo_method(this, "_update_varying_tree");
4135
undo_redo->commit_action();
4136
}
4137
4138
void VisualShaderEditor::_remove_varying(const String &p_name) {
4139
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4140
undo_redo->create_action(vformat(TTR("Remove Varying from Visual Shader: %s"), p_name));
4141
4142
VisualShader::VaryingMode var_mode = visual_shader->get_varying_mode(p_name);
4143
4144
undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", p_name);
4145
undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", p_name, var_mode, visual_shader->get_varying_type(p_name));
4146
4147
undo_redo->add_do_method(this, "_update_varyings");
4148
undo_redo->add_undo_method(this, "_update_varyings");
4149
4150
for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
4151
if (var_mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
4152
continue;
4153
}
4154
4155
VisualShader::Type type = VisualShader::Type(i);
4156
Vector<int> nodes = visual_shader->get_node_list(type);
4157
4158
for (int j = 0; j < nodes.size(); j++) {
4159
int node_id = nodes[j];
4160
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
4161
Ref<VisualShaderNodeVarying> var = vsnode;
4162
4163
if (var.is_valid()) {
4164
String var_name = var->get_varying_name();
4165
4166
if (var_name == p_name) {
4167
undo_redo->add_do_method(var.ptr(), "set_varying_name", "[None]");
4168
undo_redo->add_undo_method(var.ptr(), "set_varying_name", var_name);
4169
undo_redo->add_do_method(var.ptr(), "set_varying_type", VisualShader::VARYING_TYPE_FLOAT);
4170
undo_redo->add_undo_method(var.ptr(), "set_varying_type", var->get_varying_type());
4171
}
4172
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
4173
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
4174
}
4175
}
4176
4177
List<VisualShader::Connection> node_connections;
4178
visual_shader->get_node_connections(type, &node_connections);
4179
4180
for (VisualShader::Connection &E : node_connections) {
4181
Ref<VisualShaderNodeVaryingGetter> var_getter = Object::cast_to<VisualShaderNodeVaryingGetter>(visual_shader->get_node(type, E.from_node).ptr());
4182
if (var_getter.is_valid() && E.from_port > 0) {
4183
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4184
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4185
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4186
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4187
}
4188
Ref<VisualShaderNodeVaryingSetter> var_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(visual_shader->get_node(type, E.to_node).ptr());
4189
if (var_setter.is_valid() && E.to_port > 0) {
4190
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4191
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4192
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4193
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4194
}
4195
}
4196
}
4197
4198
undo_redo->add_do_method(this, "_update_varying_tree");
4199
undo_redo->add_undo_method(this, "_update_varying_tree");
4200
undo_redo->commit_action();
4201
}
4202
4203
void VisualShaderEditor::_update_varyings() {
4204
VisualShaderNodeVarying::clear_varyings(visual_shader->get_rid());
4205
4206
for (int i = 0; i < visual_shader->get_varyings_count(); i++) {
4207
const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
4208
4209
if (var != nullptr) {
4210
VisualShaderNodeVarying::add_varying(visual_shader->get_rid(), var->name, var->mode, var->type);
4211
}
4212
}
4213
}
4214
4215
void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
4216
VisualShader::Type type = get_current_shader_type();
4217
drag_buffer.push_back({ type, p_node, p_from / cached_theme_base_scale, p_to / cached_theme_base_scale });
4218
if (!drag_dirty) {
4219
callable_mp(this, &VisualShaderEditor::_nodes_dragged).call_deferred();
4220
}
4221
drag_dirty = true;
4222
}
4223
4224
void VisualShaderEditor::_nodes_dragged() {
4225
drag_dirty = false;
4226
4227
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4228
if (frame_node_id_to_link_to == -1) {
4229
undo_redo->create_action(TTR("Move VisualShader Node(s)"));
4230
} else {
4231
undo_redo->create_action(TTR("Move and Attach VisualShader Node(s) to parent frame"));
4232
}
4233
4234
for (const DragOp &E : drag_buffer) {
4235
undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.to);
4236
undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.from);
4237
undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.to);
4238
undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.from);
4239
}
4240
4241
for (const int node_id : nodes_link_to_frame_buffer) {
4242
VisualShader::Type type = get_current_shader_type();
4243
Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, node_id);
4244
4245
undo_redo->add_do_method(visual_shader.ptr(), "attach_node_to_frame", type, node_id, frame_node_id_to_link_to);
4246
undo_redo->add_do_method(graph_plugin.ptr(), "attach_node_to_frame", type, node_id, frame_node_id_to_link_to);
4247
undo_redo->add_undo_method(graph_plugin.ptr(), "detach_node_from_frame", type, node_id);
4248
undo_redo->add_undo_method(visual_shader.ptr(), "detach_node_from_frame", type, node_id);
4249
}
4250
4251
undo_redo->commit_action();
4252
4253
_handle_node_drop_on_connection();
4254
4255
drag_buffer.clear();
4256
nodes_link_to_frame_buffer.clear();
4257
frame_node_id_to_link_to = -1;
4258
}
4259
4260
void VisualShaderEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
4261
VisualShader::Type type = get_current_shader_type();
4262
4263
int from = p_from.to_int();
4264
int to = p_to.to_int();
4265
bool swap = last_to_node != -1 && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
4266
4267
if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) {
4268
return;
4269
}
4270
4271
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4272
undo_redo->create_action(TTR("Nodes Connected"));
4273
4274
List<VisualShader::Connection> conns;
4275
visual_shader->get_node_connections(type, &conns);
4276
4277
for (const VisualShader::Connection &E : conns) {
4278
if (E.to_node == to && E.to_port == p_to_index) {
4279
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4280
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4281
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4282
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4283
4284
if (swap) {
4285
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4286
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4287
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4288
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4289
}
4290
break;
4291
}
4292
}
4293
4294
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4295
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4296
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4297
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4298
4299
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, from);
4300
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, from);
4301
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to);
4302
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to);
4303
undo_redo->commit_action();
4304
4305
last_to_node = -1;
4306
last_to_port = -1;
4307
}
4308
4309
void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
4310
graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
4311
4312
VisualShader::Type type = get_current_shader_type();
4313
4314
int from = p_from.to_int();
4315
int to = p_to.to_int();
4316
4317
last_to_node = to;
4318
last_to_port = p_to_index;
4319
4320
info_label->show();
4321
4322
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4323
undo_redo->create_action(TTR("Nodes Disconnected"));
4324
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4325
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4326
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4327
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4328
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to);
4329
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to);
4330
undo_redo->commit_action();
4331
}
4332
4333
void VisualShaderEditor::_connection_drag_ended() {
4334
info_label->hide();
4335
}
4336
4337
void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
4338
from_node = p_from.to_int();
4339
from_slot = p_from_slot;
4340
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
4341
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
4342
Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), from_node);
4343
if (node.is_valid()) {
4344
output_port_type = node->get_output_port_type(from_slot);
4345
}
4346
_show_members_dialog(true, input_port_type, output_port_type);
4347
}
4348
4349
void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) {
4350
to_node = p_to.to_int();
4351
to_slot = p_to_slot;
4352
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
4353
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
4354
Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), to_node);
4355
if (node.is_valid()) {
4356
input_port_type = node->get_input_port_type(to_slot);
4357
}
4358
_show_members_dialog(true, input_port_type, output_port_type);
4359
}
4360
4361
bool VisualShaderEditor::_check_node_drop_on_connection(const Vector2 &p_position, Ref<GraphEdit::Connection> *r_closest_connection, int *r_from_port, int *r_to_port) {
4362
VisualShader::Type shader_type = get_current_shader_type();
4363
4364
// Get selected graph node.
4365
Ref<VisualShaderNode> selected_vsnode;
4366
int selected_node_id = -1;
4367
int selected_node_count = 0;
4368
Rect2 selected_node_rect;
4369
4370
for (int i = 0; i < graph->get_child_count(); i++) {
4371
GraphNode *graph_node = Object::cast_to<GraphNode>(graph->get_child(i));
4372
if (graph_node && graph_node->is_selected()) {
4373
selected_node_id = String(graph_node->get_name()).to_int();
4374
Ref<VisualShaderNode> vsnode = visual_shader->get_node(shader_type, selected_node_id);
4375
if (!vsnode->is_deletable()) {
4376
continue;
4377
}
4378
4379
selected_node_count += 1;
4380
4381
Ref<VisualShaderNode> node = visual_shader->get_node(shader_type, selected_node_id);
4382
selected_vsnode = node;
4383
selected_node_rect = graph_node->get_rect();
4384
}
4385
}
4386
4387
// Only a single node - which has both input and output ports but is not connected yet - can be inserted.
4388
if (selected_node_count != 1 || selected_vsnode.is_null()) {
4389
return false;
4390
}
4391
4392
// Check whether the dragged node was dropped over a connection.
4393
List<Ref<GraphEdit::Connection>> intersecting_connections = graph->get_connections_intersecting_with_rect(selected_node_rect);
4394
4395
if (intersecting_connections.is_empty()) {
4396
return false;
4397
}
4398
4399
Ref<GraphEdit::Connection> intersecting_connection = intersecting_connections.front()->get();
4400
4401
if (selected_vsnode->is_any_port_connected() || selected_vsnode->get_input_port_count() == 0 || selected_vsnode->get_output_port_count() == 0) {
4402
return false;
4403
}
4404
4405
VisualShaderNode::PortType original_port_type_from = visual_shader->get_node(shader_type, String(intersecting_connection->from_node).to_int())->get_output_port_type(intersecting_connection->from_port);
4406
VisualShaderNode::PortType original_port_type_to = visual_shader->get_node(shader_type, String(intersecting_connection->to_node).to_int())->get_input_port_type(intersecting_connection->to_port);
4407
4408
Ref<VisualShaderNodeReroute> reroute_node = selected_vsnode;
4409
4410
// Searching for the default port or the first compatible input port of the node to insert.
4411
int _to_port = -1;
4412
for (int i = 0; i < selected_vsnode->get_input_port_count(); i++) {
4413
if (visual_shader->is_port_types_compatible(original_port_type_from, selected_vsnode->get_input_port_type(i)) || reroute_node.is_valid()) {
4414
if (i == selected_vsnode->get_default_input_port(original_port_type_from)) {
4415
_to_port = i;
4416
break;
4417
} else if (_to_port == -1) {
4418
_to_port = i;
4419
}
4420
}
4421
}
4422
4423
// Searching for the first compatible output port of the node to insert.
4424
int _from_port = -1;
4425
for (int i = 0; i < selected_vsnode->get_output_port_count(); i++) {
4426
if (visual_shader->is_port_types_compatible(selected_vsnode->get_output_port_type(i), original_port_type_to) || reroute_node.is_valid()) {
4427
_from_port = i;
4428
break;
4429
}
4430
}
4431
4432
if (_to_port == -1 || _from_port == -1) {
4433
return false;
4434
}
4435
4436
if (r_closest_connection != nullptr) {
4437
*r_closest_connection = intersecting_connection;
4438
}
4439
if (r_from_port != nullptr) {
4440
*r_from_port = _from_port;
4441
}
4442
if (r_to_port != nullptr) {
4443
*r_to_port = _to_port;
4444
}
4445
4446
return true;
4447
}
4448
4449
void VisualShaderEditor::_handle_node_drop_on_connection() {
4450
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4451
undo_redo->create_action(TTR("Insert node"));
4452
4453
// Check whether the dragged node was dropped over a connection.
4454
Ref<GraphEdit::Connection> closest_connection;
4455
int _from_port = -1;
4456
int _to_port = -1;
4457
4458
if (!_check_node_drop_on_connection(graph->get_local_mouse_position(), &closest_connection, &_from_port, &_to_port)) {
4459
return;
4460
}
4461
4462
int selected_node_id = drag_buffer.front()->get().node;
4463
VisualShader::Type shader_type = get_current_shader_type();
4464
Ref<VisualShaderNode> selected_vsnode = visual_shader->get_node(shader_type, selected_node_id);
4465
4466
// Delete the old connection.
4467
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4468
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4469
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4470
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4471
4472
// Add the connection to the dropped node.
4473
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, selected_node_id, _to_port);
4474
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, selected_node_id, _to_port);
4475
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, selected_node_id, _to_port);
4476
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", shader_type, String(closest_connection->from_node).to_int(), closest_connection->from_port, selected_node_id, _to_port);
4477
4478
// Add the connection from the dropped node.
4479
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", shader_type, selected_node_id, _from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4480
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", shader_type, selected_node_id, _from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4481
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", shader_type, selected_node_id, _from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4482
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", shader_type, selected_node_id, _from_port, String(closest_connection->to_node).to_int(), closest_connection->to_port);
4483
4484
undo_redo->commit_action();
4485
4486
call_deferred(SNAME("_update_graph"));
4487
}
4488
4489
void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
4490
VisualShader::Type type = VisualShader::Type(p_type);
4491
List<VisualShader::Connection> conns;
4492
visual_shader->get_node_connections(type, &conns);
4493
4494
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4495
for (const int &F : p_nodes) {
4496
for (const VisualShader::Connection &E : conns) {
4497
if (E.from_node == F || E.to_node == F) {
4498
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4499
}
4500
}
4501
}
4502
4503
// The VS nodes need to be added before attaching them to frames.
4504
for (const int &F : p_nodes) {
4505
Ref<VisualShaderNode> node = visual_shader->get_node(type, F);
4506
undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F), F);
4507
undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F, false, false);
4508
}
4509
4510
// Update frame references.
4511
for (const int &node_id : p_nodes) {
4512
Ref<VisualShaderNodeFrame> frame = visual_shader->get_node(type, node_id);
4513
if (frame.is_valid()) {
4514
for (const int &attached_node_id : frame->get_attached_nodes()) {
4515
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", type, attached_node_id);
4516
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", type, attached_node_id);
4517
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", type, attached_node_id, node_id);
4518
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", type, attached_node_id, node_id);
4519
}
4520
}
4521
4522
Ref<VisualShaderNode> node = visual_shader->get_node(type, node_id);
4523
if (node->get_frame() == -1) {
4524
continue;
4525
}
4526
4527
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", type, node_id);
4528
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", type, node_id);
4529
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", type, node_id, node->get_frame());
4530
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", type, node_id, node->get_frame());
4531
}
4532
4533
// Restore size of the frame nodes.
4534
for (const int &F : p_nodes) {
4535
Ref<VisualShaderNodeFrame> frame = visual_shader->get_node(type, F);
4536
if (frame.is_valid()) {
4537
undo_redo->add_undo_method(this, "_set_node_size", type, F, frame->get_size());
4538
}
4539
}
4540
4541
HashSet<String> parameter_names;
4542
4543
for (const int &F : p_nodes) {
4544
Ref<VisualShaderNode> node = visual_shader->get_node(type, F);
4545
4546
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F);
4547
4548
VisualShaderNodeParameter *parameter = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4549
if (parameter) {
4550
parameter_names.insert(parameter->get_parameter_name());
4551
}
4552
}
4553
4554
List<VisualShader::Connection> used_conns;
4555
for (const int &F : p_nodes) {
4556
for (const VisualShader::Connection &E : conns) {
4557
if (E.from_node == F || E.to_node == F) {
4558
bool cancel = false;
4559
for (const VisualShader::Connection &R : used_conns) {
4560
if (R.from_node == E.from_node && R.from_port == E.from_port && R.to_node == E.to_node && R.to_port == E.to_port) {
4561
cancel = true; // to avoid ERR_ALREADY_EXISTS warning
4562
break;
4563
}
4564
}
4565
if (!cancel) {
4566
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4567
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4568
used_conns.push_back(E);
4569
}
4570
}
4571
}
4572
}
4573
4574
// Delete nodes from the graph.
4575
for (const int &F : p_nodes) {
4576
undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F, false);
4577
}
4578
4579
// Update parameter refs if any parameter has been deleted.
4580
if (parameter_names.size() > 0) {
4581
undo_redo->add_do_method(this, "_update_parameters", true);
4582
undo_redo->add_undo_method(this, "_update_parameters", true);
4583
4584
_update_parameter_refs(parameter_names);
4585
}
4586
}
4587
4588
void VisualShaderEditor::_replace_node(VisualShader::Type p_type_id, int p_node_id, const StringName &p_from, const StringName &p_to) {
4589
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4590
undo_redo->add_do_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_to);
4591
undo_redo->add_undo_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_from);
4592
}
4593
4594
void VisualShaderEditor::_update_constant(VisualShader::Type p_type_id, int p_node_id, const Variant &p_var, int p_preview_port) {
4595
Ref<VisualShaderNode> node = visual_shader->get_node(p_type_id, p_node_id);
4596
ERR_FAIL_COND(node.is_null());
4597
ERR_FAIL_COND(!node->has_method("set_constant"));
4598
node->call("set_constant", p_var);
4599
if (p_preview_port != -1) {
4600
node->set_output_port_for_preview(p_preview_port);
4601
}
4602
}
4603
4604
void VisualShaderEditor::_update_parameter(VisualShader::Type p_type_id, int p_node_id, const Variant &p_var, int p_preview_port) {
4605
Ref<VisualShaderNodeParameter> parameter = visual_shader->get_node(p_type_id, p_node_id);
4606
ERR_FAIL_COND(parameter.is_null());
4607
4608
String valid_name = visual_shader->validate_parameter_name(parameter->get_parameter_name(), parameter);
4609
parameter->set_parameter_name(valid_name);
4610
graph_plugin->set_parameter_name(p_type_id, p_node_id, valid_name);
4611
4612
if (parameter->has_method("set_default_value_enabled")) {
4613
parameter->call("set_default_value_enabled", true);
4614
parameter->call("set_default_value", p_var);
4615
}
4616
if (p_preview_port != -1) {
4617
parameter->set_output_port_for_preview(p_preview_port);
4618
}
4619
}
4620
4621
void VisualShaderEditor::_convert_constants_to_parameters(bool p_vice_versa) {
4622
VisualShader::Type type_id = get_current_shader_type();
4623
4624
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4625
if (!p_vice_versa) {
4626
undo_redo->create_action(TTR("Convert Constant Node(s) To Parameter(s)"));
4627
} else {
4628
undo_redo->create_action(TTR("Convert Parameter Node(s) To Constant(s)"));
4629
}
4630
4631
const HashSet<int> &current_set = p_vice_versa ? selected_parameters : selected_constants;
4632
HashSet<String> deleted_names;
4633
4634
for (const int &E : current_set) {
4635
int node_id = E;
4636
Ref<VisualShaderNode> node = visual_shader->get_node(type_id, node_id);
4637
bool caught = false;
4638
Variant var;
4639
4640
// float
4641
if (!p_vice_versa) {
4642
Ref<VisualShaderNodeFloatConstant> float_const = Object::cast_to<VisualShaderNodeFloatConstant>(node.ptr());
4643
if (float_const.is_valid()) {
4644
_replace_node(type_id, node_id, "VisualShaderNodeFloatConstant", "VisualShaderNodeFloatParameter");
4645
var = float_const->get_constant();
4646
caught = true;
4647
}
4648
} else {
4649
Ref<VisualShaderNodeFloatParameter> float_parameter = Object::cast_to<VisualShaderNodeFloatParameter>(node.ptr());
4650
if (float_parameter.is_valid()) {
4651
_replace_node(type_id, node_id, "VisualShaderNodeFloatParameter", "VisualShaderNodeFloatConstant");
4652
var = float_parameter->get_default_value();
4653
caught = true;
4654
}
4655
}
4656
4657
// int
4658
if (!caught) {
4659
if (!p_vice_versa) {
4660
Ref<VisualShaderNodeIntConstant> int_const = Object::cast_to<VisualShaderNodeIntConstant>(node.ptr());
4661
if (int_const.is_valid()) {
4662
_replace_node(type_id, node_id, "VisualShaderNodeIntConstant", "VisualShaderNodeIntParameter");
4663
var = int_const->get_constant();
4664
caught = true;
4665
}
4666
} else {
4667
Ref<VisualShaderNodeIntParameter> int_parameter = Object::cast_to<VisualShaderNodeIntParameter>(node.ptr());
4668
if (int_parameter.is_valid()) {
4669
_replace_node(type_id, node_id, "VisualShaderNodeIntParameter", "VisualShaderNodeIntConstant");
4670
var = int_parameter->get_default_value();
4671
caught = true;
4672
}
4673
}
4674
}
4675
4676
// boolean
4677
if (!caught) {
4678
if (!p_vice_versa) {
4679
Ref<VisualShaderNodeBooleanConstant> boolean_const = Object::cast_to<VisualShaderNodeBooleanConstant>(node.ptr());
4680
if (boolean_const.is_valid()) {
4681
_replace_node(type_id, node_id, "VisualShaderNodeBooleanConstant", "VisualShaderNodeBooleanParameter");
4682
var = boolean_const->get_constant();
4683
caught = true;
4684
}
4685
} else {
4686
Ref<VisualShaderNodeBooleanParameter> boolean_parameter = Object::cast_to<VisualShaderNodeBooleanParameter>(node.ptr());
4687
if (boolean_parameter.is_valid()) {
4688
_replace_node(type_id, node_id, "VisualShaderNodeBooleanParameter", "VisualShaderNodeBooleanConstant");
4689
var = boolean_parameter->get_default_value();
4690
caught = true;
4691
}
4692
}
4693
}
4694
4695
// vec2
4696
if (!caught) {
4697
if (!p_vice_versa) {
4698
Ref<VisualShaderNodeVec2Constant> vec2_const = Object::cast_to<VisualShaderNodeVec2Constant>(node.ptr());
4699
if (vec2_const.is_valid()) {
4700
_replace_node(type_id, node_id, "VisualShaderNodeVec2Constant", "VisualShaderNodeVec2Parameter");
4701
var = vec2_const->get_constant();
4702
caught = true;
4703
}
4704
} else {
4705
Ref<VisualShaderNodeVec2Parameter> vec2_parameter = Object::cast_to<VisualShaderNodeVec2Parameter>(node.ptr());
4706
if (vec2_parameter.is_valid()) {
4707
_replace_node(type_id, node_id, "VisualShaderNodeVec2Parameter", "VisualShaderNodeVec2Constant");
4708
var = vec2_parameter->get_default_value();
4709
caught = true;
4710
}
4711
}
4712
}
4713
4714
// vec3
4715
if (!caught) {
4716
if (!p_vice_versa) {
4717
Ref<VisualShaderNodeVec3Constant> vec3_const = Object::cast_to<VisualShaderNodeVec3Constant>(node.ptr());
4718
if (vec3_const.is_valid()) {
4719
_replace_node(type_id, node_id, "VisualShaderNodeVec3Constant", "VisualShaderNodeVec3Parameter");
4720
var = vec3_const->get_constant();
4721
caught = true;
4722
}
4723
} else {
4724
Ref<VisualShaderNodeVec3Parameter> vec3_parameter = Object::cast_to<VisualShaderNodeVec3Parameter>(node.ptr());
4725
if (vec3_parameter.is_valid()) {
4726
_replace_node(type_id, node_id, "VisualShaderNodeVec3Parameter", "VisualShaderNodeVec3Constant");
4727
var = vec3_parameter->get_default_value();
4728
caught = true;
4729
}
4730
}
4731
}
4732
4733
// vec4
4734
if (!caught) {
4735
if (!p_vice_versa) {
4736
Ref<VisualShaderNodeVec4Constant> vec4_const = Object::cast_to<VisualShaderNodeVec4Constant>(node.ptr());
4737
if (vec4_const.is_valid()) {
4738
_replace_node(type_id, node_id, "VisualShaderNodeVec4Constant", "VisualShaderNodeVec4Parameter");
4739
var = vec4_const->get_constant();
4740
caught = true;
4741
}
4742
} else {
4743
Ref<VisualShaderNodeVec4Parameter> vec4_parameter = Object::cast_to<VisualShaderNodeVec4Parameter>(node.ptr());
4744
if (vec4_parameter.is_valid()) {
4745
_replace_node(type_id, node_id, "VisualShaderNodeVec4Parameter", "VisualShaderNodeVec4Constant");
4746
var = vec4_parameter->get_default_value();
4747
caught = true;
4748
}
4749
}
4750
}
4751
4752
// color
4753
if (!caught) {
4754
if (!p_vice_versa) {
4755
Ref<VisualShaderNodeColorConstant> color_const = Object::cast_to<VisualShaderNodeColorConstant>(node.ptr());
4756
if (color_const.is_valid()) {
4757
_replace_node(type_id, node_id, "VisualShaderNodeColorConstant", "VisualShaderNodeColorParameter");
4758
var = color_const->get_constant();
4759
caught = true;
4760
}
4761
} else {
4762
Ref<VisualShaderNodeColorParameter> color_parameter = Object::cast_to<VisualShaderNodeColorParameter>(node.ptr());
4763
if (color_parameter.is_valid()) {
4764
_replace_node(type_id, node_id, "VisualShaderNodeColorParameter", "VisualShaderNodeColorConstant");
4765
var = color_parameter->get_default_value();
4766
caught = true;
4767
}
4768
}
4769
}
4770
4771
// transform
4772
if (!caught) {
4773
if (!p_vice_versa) {
4774
Ref<VisualShaderNodeTransformConstant> transform_const = Object::cast_to<VisualShaderNodeTransformConstant>(node.ptr());
4775
if (transform_const.is_valid()) {
4776
_replace_node(type_id, node_id, "VisualShaderNodeTransformConstant", "VisualShaderNodeTransformParameter");
4777
var = transform_const->get_constant();
4778
caught = true;
4779
}
4780
} else {
4781
Ref<VisualShaderNodeTransformParameter> transform_parameter = Object::cast_to<VisualShaderNodeTransformParameter>(node.ptr());
4782
if (transform_parameter.is_valid()) {
4783
_replace_node(type_id, node_id, "VisualShaderNodeTransformParameter", "VisualShaderNodeTransformConstant");
4784
var = transform_parameter->get_default_value();
4785
caught = true;
4786
}
4787
}
4788
}
4789
ERR_CONTINUE(!caught);
4790
int preview_port = node->get_output_port_for_preview();
4791
4792
if (!p_vice_versa) {
4793
undo_redo->add_do_method(this, "_update_parameter", type_id, node_id, var, preview_port);
4794
undo_redo->add_undo_method(this, "_update_constant", type_id, node_id, var, preview_port);
4795
} else {
4796
undo_redo->add_do_method(this, "_update_constant", type_id, node_id, var, preview_port);
4797
undo_redo->add_undo_method(this, "_update_parameter", type_id, node_id, var, preview_port);
4798
4799
Ref<VisualShaderNodeParameter> parameter = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4800
ERR_CONTINUE(parameter.is_null());
4801
4802
deleted_names.insert(parameter->get_parameter_name());
4803
}
4804
4805
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, node_id);
4806
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, node_id);
4807
}
4808
4809
undo_redo->add_do_method(this, "_update_parameters", true);
4810
undo_redo->add_undo_method(this, "_update_parameters", true);
4811
4812
if (deleted_names.size() > 0) {
4813
_update_parameter_refs(deleted_names);
4814
}
4815
4816
undo_redo->commit_action();
4817
}
4818
4819
void VisualShaderEditor::_detach_nodes_from_frame(int p_type, const List<int> &p_nodes) {
4820
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4821
for (int node_id : p_nodes) {
4822
Ref<VisualShaderNode> node = visual_shader->get_node((VisualShader::Type)p_type, node_id);
4823
if (node.is_null()) {
4824
continue;
4825
}
4826
int frame_id = node->get_frame();
4827
if (frame_id != -1) {
4828
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", p_type, node_id);
4829
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", p_type, node_id);
4830
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", p_type, node_id, frame_id);
4831
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", p_type, node_id, frame_id);
4832
}
4833
}
4834
}
4835
4836
void VisualShaderEditor::_detach_nodes_from_frame_request() {
4837
// Called from context menu.
4838
List<int> to_detach_node_ids;
4839
for (int i = 0; i < graph->get_child_count(); i++) {
4840
GraphElement *gn = Object::cast_to<GraphElement>(graph->get_child(i));
4841
if (gn) {
4842
int id = String(gn->get_name()).to_int();
4843
if (gn->is_selected()) {
4844
to_detach_node_ids.push_back(id);
4845
}
4846
}
4847
}
4848
if (to_detach_node_ids.is_empty()) {
4849
return;
4850
}
4851
4852
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4853
undo_redo->create_action(TTR("Detach VisualShader Node(s) from Frame"));
4854
_detach_nodes_from_frame(get_current_shader_type(), to_detach_node_ids);
4855
undo_redo->commit_action();
4856
}
4857
4858
void VisualShaderEditor::_delete_node_request(int p_type, int p_node) {
4859
Ref<VisualShaderNode> node = visual_shader->get_node((VisualShader::Type)p_type, p_node);
4860
if (!node->is_deletable()) {
4861
return;
4862
}
4863
4864
List<int> to_erase;
4865
to_erase.push_back(p_node);
4866
4867
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4868
undo_redo->create_action(TTR("Delete VisualShader Node"));
4869
_delete_nodes(p_type, to_erase);
4870
undo_redo->commit_action();
4871
}
4872
4873
void VisualShaderEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) {
4874
List<int> to_erase;
4875
4876
if (p_nodes.is_empty()) {
4877
// Called from context menu.
4878
for (int i = 0; i < graph->get_child_count(); i++) {
4879
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
4880
if (!graph_element) {
4881
continue;
4882
}
4883
4884
VisualShader::Type type = get_current_shader_type();
4885
int id = String(graph_element->get_name()).to_int();
4886
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4887
if (vsnode->is_deletable() && graph_element->is_selected()) {
4888
to_erase.push_back(graph_element->get_name().operator String().to_int());
4889
}
4890
}
4891
} else {
4892
VisualShader::Type type = get_current_shader_type();
4893
for (int i = 0; i < p_nodes.size(); i++) {
4894
int id = p_nodes[i].operator String().to_int();
4895
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4896
if (vsnode->is_deletable()) {
4897
to_erase.push_back(id);
4898
}
4899
}
4900
}
4901
4902
if (to_erase.is_empty()) {
4903
return;
4904
}
4905
4906
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4907
undo_redo->create_action(TTR("Delete VisualShader Node(s)"));
4908
_delete_nodes(get_current_shader_type(), to_erase);
4909
undo_redo->commit_action();
4910
}
4911
4912
void VisualShaderEditor::_node_selected(Object *p_node) {
4913
VisualShader::Type type = get_current_shader_type();
4914
4915
GraphElement *graph_element = Object::cast_to<GraphElement>(p_node);
4916
ERR_FAIL_NULL(graph_element);
4917
4918
int id = String(graph_element->get_name()).to_int();
4919
4920
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4921
ERR_FAIL_COND(vsnode.is_null());
4922
}
4923
4924
void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
4925
Ref<InputEventMouseMotion> mm = p_event;
4926
Ref<InputEventMouseButton> mb = p_event;
4927
VisualShader::Type type = get_current_shader_type();
4928
4929
// Highlight valid connection on which a node can be dropped.
4930
if (mm.is_valid() && mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
4931
Ref<GraphEdit::Connection> closest_connection;
4932
graph->reset_all_connection_activity();
4933
if (_check_node_drop_on_connection(graph->get_local_mouse_position(), &closest_connection)) {
4934
graph->set_connection_activity(closest_connection->from_node, closest_connection->from_port, closest_connection->to_node, closest_connection->to_port, 1.0);
4935
}
4936
}
4937
4938
Ref<VisualShaderNode> selected_vsnode;
4939
// Right click actions.
4940
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
4941
selected_constants.clear();
4942
selected_parameters.clear();
4943
selected_frame = -1;
4944
selected_float_constant = -1;
4945
4946
List<int> selected_deletable_graph_elements;
4947
List<GraphElement *> selected_graph_elements;
4948
for (int i = 0; i < graph->get_child_count(); i++) {
4949
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
4950
if (!graph_element) {
4951
continue;
4952
}
4953
int id = String(graph_element->get_name()).to_int();
4954
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4955
4956
if (!graph_element->is_selected()) {
4957
continue;
4958
}
4959
4960
selected_graph_elements.push_back(graph_element);
4961
4962
if (!vsnode->is_deletable()) {
4963
continue;
4964
}
4965
4966
selected_deletable_graph_elements.push_back(id);
4967
4968
Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
4969
selected_vsnode = node;
4970
4971
VisualShaderNodeFrame *frame_node = Object::cast_to<VisualShaderNodeFrame>(node.ptr());
4972
if (frame_node != nullptr) {
4973
selected_frame = id;
4974
}
4975
VisualShaderNodeConstant *constant_node = Object::cast_to<VisualShaderNodeConstant>(node.ptr());
4976
if (constant_node != nullptr) {
4977
selected_constants.insert(id);
4978
}
4979
VisualShaderNodeFloatConstant *float_constant_node = Object::cast_to<VisualShaderNodeFloatConstant>(node.ptr());
4980
if (float_constant_node != nullptr) {
4981
selected_float_constant = id;
4982
}
4983
VisualShaderNodeParameter *parameter_node = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4984
if (parameter_node != nullptr && parameter_node->is_convertible_to_constant()) {
4985
selected_parameters.insert(id);
4986
}
4987
}
4988
4989
if (selected_deletable_graph_elements.size() > 1) {
4990
selected_frame = -1;
4991
selected_float_constant = -1;
4992
}
4993
4994
bool copy_buffer_empty = true;
4995
for (const CopyItem &item : copy_items_buffer) {
4996
if (!item.disabled) {
4997
copy_buffer_empty = false;
4998
break;
4999
}
5000
}
5001
5002
menu_point = graph->get_local_mouse_position();
5003
Point2 gpos = get_screen_position() + get_local_mouse_position();
5004
5005
Ref<GraphEdit::Connection> closest_connection = graph->get_closest_connection_at_point(menu_point);
5006
if (closest_connection.is_valid()) {
5007
clicked_connection = closest_connection;
5008
saved_node_pos = graph->get_local_mouse_position();
5009
saved_node_pos_dirty = true;
5010
connection_popup_menu->set_position(gpos);
5011
connection_popup_menu->reset_size();
5012
connection_popup_menu->popup();
5013
} else if (selected_graph_elements.is_empty() && copy_buffer_empty) {
5014
_show_members_dialog(true);
5015
} else {
5016
popup_menu->set_item_disabled(NodeMenuOptions::CUT, selected_deletable_graph_elements.is_empty());
5017
popup_menu->set_item_disabled(NodeMenuOptions::COPY, selected_deletable_graph_elements.is_empty());
5018
popup_menu->set_item_disabled(NodeMenuOptions::PASTE, copy_buffer_empty);
5019
popup_menu->set_item_disabled(NodeMenuOptions::DELETE_, selected_deletable_graph_elements.is_empty());
5020
popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, selected_deletable_graph_elements.is_empty());
5021
popup_menu->set_item_disabled(NodeMenuOptions::CLEAR_COPY_BUFFER, copy_buffer_empty);
5022
5023
int temp = popup_menu->get_item_index(NodeMenuOptions::SEPARATOR2);
5024
if (temp != -1) {
5025
popup_menu->remove_item(temp);
5026
}
5027
temp = popup_menu->get_item_index(NodeMenuOptions::FLOAT_CONSTANTS);
5028
if (temp != -1) {
5029
popup_menu->remove_item(temp);
5030
}
5031
temp = popup_menu->get_item_index(NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS);
5032
if (temp != -1) {
5033
popup_menu->remove_item(temp);
5034
}
5035
temp = popup_menu->get_item_index(NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS);
5036
if (temp != -1) {
5037
popup_menu->remove_item(temp);
5038
}
5039
temp = popup_menu->get_item_index(NodeMenuOptions::SEPARATOR3);
5040
if (temp != -1) {
5041
popup_menu->remove_item(temp);
5042
}
5043
temp = popup_menu->get_item_index(NodeMenuOptions::UNLINK_FROM_PARENT_FRAME);
5044
if (temp != -1) {
5045
popup_menu->remove_item(temp);
5046
}
5047
temp = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_TITLE);
5048
if (temp != -1) {
5049
popup_menu->remove_item(temp);
5050
}
5051
temp = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
5052
if (temp != -1) {
5053
popup_menu->remove_item(temp);
5054
}
5055
temp = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_COLOR);
5056
if (temp != -1) {
5057
popup_menu->remove_item(temp);
5058
}
5059
temp = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5060
if (temp != -1) {
5061
popup_menu->remove_item(temp);
5062
}
5063
5064
if (selected_constants.size() > 0 || selected_parameters.size() > 0) {
5065
popup_menu->add_separator("", NodeMenuOptions::SEPARATOR2);
5066
5067
if (selected_float_constant != -1) {
5068
if (!constants_submenu) {
5069
constants_submenu = memnew(PopupMenu);
5070
5071
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
5072
constants_submenu->add_item(float_constant_defs[i].name, i);
5073
}
5074
constants_submenu->connect("index_pressed", callable_mp(this, &VisualShaderEditor::_float_constant_selected));
5075
}
5076
popup_menu->add_submenu_node_item(TTR("Float Constants"), constants_submenu, int(NodeMenuOptions::FLOAT_CONSTANTS));
5077
}
5078
5079
if (selected_constants.size() > 0) {
5080
popup_menu->add_item(TTR("Convert Constant(s) to Parameter(s)"), NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS);
5081
}
5082
5083
if (selected_parameters.size() > 0) {
5084
popup_menu->add_item(TTR("Convert Parameter(s) to Constant(s)"), NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS);
5085
}
5086
}
5087
5088
// Check if any selected node is attached to a frame.
5089
bool is_attached_to_frame = false;
5090
for (GraphElement *graph_element : selected_graph_elements) {
5091
if (graph->get_element_frame(graph_element->get_name())) {
5092
is_attached_to_frame = true;
5093
break;
5094
}
5095
}
5096
5097
if (is_attached_to_frame) {
5098
popup_menu->add_item(TTR("Detach from Parent Frame"), NodeMenuOptions::UNLINK_FROM_PARENT_FRAME);
5099
}
5100
5101
if (selected_frame != -1) {
5102
popup_menu->add_separator("", NodeMenuOptions::SEPARATOR3);
5103
popup_menu->add_item(TTR("Set Frame Title"), NodeMenuOptions::SET_FRAME_TITLE);
5104
popup_menu->add_check_item(TTR("Enable Auto Shrink"), NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5105
popup_menu->add_check_item(TTR("Enable Tint Color"), NodeMenuOptions::ENABLE_FRAME_COLOR);
5106
5107
VisualShaderNodeFrame *frame_ref = Object::cast_to<VisualShaderNodeFrame>(selected_vsnode.ptr());
5108
if (frame_ref) {
5109
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
5110
popup_menu->set_item_checked(item_index, frame_ref->is_tint_color_enabled());
5111
if (frame_ref->is_tint_color_enabled()) {
5112
popup_menu->add_item(TTR("Set Tint Color"), NodeMenuOptions::SET_FRAME_COLOR);
5113
}
5114
5115
item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5116
popup_menu->set_item_checked(item_index, frame_ref->is_autoshrink_enabled());
5117
}
5118
}
5119
5120
popup_menu->set_position(gpos);
5121
popup_menu->reset_size();
5122
popup_menu->popup();
5123
}
5124
}
5125
}
5126
5127
void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type, VisualShaderNode::PortType p_output_port_type) {
5128
if (members_input_port_type != p_input_port_type || members_output_port_type != p_output_port_type) {
5129
members_input_port_type = p_input_port_type;
5130
members_output_port_type = p_output_port_type;
5131
_update_options_menu();
5132
}
5133
5134
if (at_mouse_pos) {
5135
saved_node_pos_dirty = true;
5136
saved_node_pos = graph->get_local_mouse_position();
5137
5138
Point2 gpos = get_screen_position() + get_local_mouse_position();
5139
members_dialog->set_position(gpos);
5140
} else {
5141
saved_node_pos_dirty = false;
5142
members_dialog->set_position(graph->get_screen_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5143
}
5144
5145
if (members_dialog->is_visible()) {
5146
members_dialog->grab_focus();
5147
return;
5148
}
5149
5150
members_dialog->popup();
5151
5152
// Keep dialog within window bounds.
5153
Rect2 window_rect = Rect2(get_window()->get_position(), get_window()->get_size());
5154
Rect2 dialog_rect = Rect2(members_dialog->get_position(), members_dialog->get_size());
5155
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5156
members_dialog->set_position(members_dialog->get_position() - difference);
5157
5158
node_filter->grab_focus();
5159
node_filter->select_all();
5160
}
5161
5162
void VisualShaderEditor::_varying_menu_id_pressed(int p_idx) {
5163
switch (VaryingMenuOptions(p_idx)) {
5164
case VaryingMenuOptions::ADD: {
5165
_show_add_varying_dialog();
5166
} break;
5167
case VaryingMenuOptions::REMOVE: {
5168
_show_remove_varying_dialog();
5169
} break;
5170
default:
5171
break;
5172
}
5173
}
5174
5175
void VisualShaderEditor::_show_add_varying_dialog() {
5176
_varying_name_changed(varying_name->get_text());
5177
5178
add_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5179
add_varying_dialog->popup();
5180
5181
varying_name->grab_focus();
5182
5183
// Keep dialog within window bounds.
5184
Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
5185
Rect2 dialog_rect = Rect2(add_varying_dialog->get_position(), add_varying_dialog->get_size());
5186
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5187
add_varying_dialog->set_position(add_varying_dialog->get_position() - difference);
5188
}
5189
5190
void VisualShaderEditor::_show_remove_varying_dialog() {
5191
remove_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5192
remove_varying_dialog->popup();
5193
5194
varyings->grab_focus();
5195
5196
// Keep dialog within window bounds.
5197
Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
5198
Rect2 dialog_rect = Rect2(remove_varying_dialog->get_position(), remove_varying_dialog->get_size());
5199
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5200
remove_varying_dialog->set_position(remove_varying_dialog->get_position() - difference);
5201
}
5202
5203
void VisualShaderEditor::_param_filter_changed(const String &p_text) {
5204
param_filter_name = p_text;
5205
5206
if (!_update_preview_parameter_tree()) {
5207
_clear_preview_param();
5208
}
5209
}
5210
5211
void VisualShaderEditor::_param_property_changed(const String &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
5212
if (p_changing) {
5213
return;
5214
}
5215
String raw_prop_name = p_property.trim_prefix("shader_parameter/");
5216
5217
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5218
5219
undo_redo->create_action(vformat(TTR("Edit Preview Parameter: %s"), p_property));
5220
undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, p_value);
5221
undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, preview_material->get(p_property));
5222
undo_redo->add_do_method(this, "_update_current_param");
5223
undo_redo->add_undo_method(this, "_update_current_param");
5224
undo_redo->commit_action();
5225
}
5226
5227
void VisualShaderEditor::_update_current_param() {
5228
if (current_prop != nullptr) {
5229
String name = current_prop->get_meta("id");
5230
if (visual_shader->_has_preview_shader_parameter(name)) {
5231
preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name));
5232
} else {
5233
preview_material->set("shader_parameter/" + name, Variant());
5234
}
5235
current_prop->update_property();
5236
current_prop->update_editor_property_status();
5237
current_prop->update_cache();
5238
}
5239
}
5240
5241
void VisualShaderEditor::_param_selected() {
5242
_clear_preview_param();
5243
5244
TreeItem *item = parameters->get_selected();
5245
selected_param_id = item->get_meta("id");
5246
5247
PropertyInfo pi = parameter_props.get(selected_param_id);
5248
EditorProperty *prop = EditorInspector::instantiate_property_editor(preview_material.ptr(), pi.type, pi.name, pi.hint, pi.hint_string, pi.usage);
5249
if (!prop) {
5250
return;
5251
}
5252
prop->connect("property_changed", callable_mp(this, &VisualShaderEditor::_param_property_changed));
5253
prop->set_h_size_flags(SIZE_EXPAND_FILL);
5254
prop->set_object_and_property(preview_material.ptr(), "shader_parameter/" + pi.name);
5255
5256
prop->set_label(TTR("Value:"));
5257
prop->update_property();
5258
prop->update_editor_property_status();
5259
prop->update_cache();
5260
5261
current_prop = prop;
5262
current_prop->set_meta("id", selected_param_id);
5263
5264
param_vbox2->add_child(prop);
5265
param_vbox->show();
5266
}
5267
5268
void VisualShaderEditor::_param_unselected() {
5269
parameters->deselect_all();
5270
5271
_clear_preview_param();
5272
}
5273
5274
void VisualShaderEditor::_help_open() {
5275
OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/visual_shaders.html", GODOT_VERSION_DOCS_URL));
5276
}
5277
5278
void VisualShaderEditor::_notification(int p_what) {
5279
switch (p_what) {
5280
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
5281
if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/panning")) {
5282
graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
5283
graph->set_warped_panning(EDITOR_GET("editors/panning/warped_mouse_panning"));
5284
}
5285
if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors")) {
5286
graph->set_minimap_opacity(EDITOR_GET("editors/visual_editors/minimap_opacity"));
5287
graph->set_grid_pattern((GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern")));
5288
graph->set_connection_lines_curvature(EDITOR_GET("editors/visual_editors/lines_curvature"));
5289
5290
_update_graph();
5291
}
5292
} break;
5293
5294
case NOTIFICATION_ENTER_TREE: {
5295
// collapse tree by default
5296
5297
TreeItem *category = members->get_root()->get_first_child();
5298
while (category) {
5299
category->set_collapsed(true);
5300
TreeItem *sub_category = category->get_first_child();
5301
while (sub_category) {
5302
sub_category->set_collapsed(true);
5303
sub_category = sub_category->get_next();
5304
}
5305
category = category->get_next();
5306
}
5307
5308
graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
5309
graph->set_warped_panning(EDITOR_GET("editors/panning/warped_mouse_panning"));
5310
} break;
5311
5312
case NOTIFICATION_THEME_CHANGED: {
5313
site_search->set_button_icon(get_editor_theme_icon(SNAME("ExternalLink")));
5314
highend_label->add_theme_color_override(SceneStringName(font_color), get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
5315
5316
param_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search")));
5317
5318
code_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("Shader")));
5319
shader_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("SubViewport")));
5320
5321
{
5322
Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
5323
Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
5324
Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
5325
Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
5326
Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
5327
Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
5328
Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
5329
Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
5330
Color error_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
5331
5332
varying_error_label->add_theme_color_override(SceneStringName(font_color), error_color);
5333
5334
for (const String &E : keyword_list) {
5335
if (ShaderLanguage::is_control_flow_keyword(E)) {
5336
syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
5337
} else {
5338
syntax_highlighter->add_keyword_color(E, keyword_color);
5339
}
5340
}
5341
5342
preview_text->begin_bulk_theme_override();
5343
preview_text->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)));
5344
preview_text->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size(SNAME("expression_size"), EditorStringName(EditorFonts)));
5345
preview_text->add_theme_color_override(SceneStringName(font_color), text_color);
5346
preview_text->end_bulk_theme_override();
5347
5348
syntax_highlighter->set_number_color(number_color);
5349
syntax_highlighter->set_symbol_color(symbol_color);
5350
syntax_highlighter->set_function_color(function_color);
5351
syntax_highlighter->set_member_variable_color(members_color);
5352
syntax_highlighter->clear_color_regions();
5353
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
5354
syntax_highlighter->add_color_region("//", "", comment_color, true);
5355
5356
preview_text->clear_comment_delimiters();
5357
preview_text->add_comment_delimiter("/*", "*/", false);
5358
preview_text->add_comment_delimiter("//", "", true);
5359
5360
error_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Panel")));
5361
error_label->begin_bulk_theme_override();
5362
error_label->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
5363
error_label->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
5364
error_label->add_theme_color_override(SceneStringName(font_color), error_color);
5365
error_label->end_bulk_theme_override();
5366
}
5367
5368
tools->set_button_icon(get_editor_theme_icon(SNAME("Tools")));
5369
preview_tools->set_button_icon(get_editor_theme_icon(SNAME("Tools")));
5370
5371
cached_theme_base_scale = get_theme_default_base_scale();
5372
5373
if (is_visible_in_tree()) {
5374
_update_graph();
5375
} else {
5376
theme_dirty = true;
5377
}
5378
update_toggle_files_button();
5379
_update_options_menu();
5380
} break;
5381
5382
case NOTIFICATION_VISIBILITY_CHANGED: {
5383
update_toggle_files_button();
5384
if (theme_dirty && is_visible_in_tree()) {
5385
theme_dirty = false;
5386
_update_graph();
5387
}
5388
} break;
5389
5390
case NOTIFICATION_DRAG_BEGIN: {
5391
Dictionary dd = get_viewport()->gui_get_drag_data();
5392
if (members->is_visible_in_tree() && dd.has("id")) {
5393
members->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
5394
}
5395
} break;
5396
5397
case NOTIFICATION_DRAG_END: {
5398
members->set_drop_mode_flags(0);
5399
} break;
5400
}
5401
}
5402
5403
void VisualShaderEditor::_scroll_offset_changed(const Vector2 &p_scroll) {
5404
if (!shader_fully_loaded) {
5405
return;
5406
}
5407
5408
panning_debounce_timer->start();
5409
}
5410
5411
void VisualShaderEditor::_node_changed(int p_id) {
5412
if (is_visible_in_tree()) {
5413
_update_graph();
5414
}
5415
}
5416
5417
void VisualShaderEditor::_nodes_linked_to_frame_request(const TypedArray<StringName> &p_nodes, const StringName &p_frame) {
5418
Vector<int> node_ids;
5419
for (int i = 0; i < p_nodes.size(); i++) {
5420
node_ids.push_back(p_nodes[i].operator String().to_int());
5421
}
5422
frame_node_id_to_link_to = p_frame.operator String().to_int();
5423
nodes_link_to_frame_buffer = node_ids;
5424
}
5425
5426
void VisualShaderEditor::_frame_rect_changed(const GraphFrame *p_frame, const Rect2 &p_new_rect) {
5427
if (p_frame == nullptr) {
5428
return;
5429
}
5430
5431
int node_id = String(p_frame->get_name()).to_int();
5432
Ref<VisualShaderNodeResizableBase> vsnode = visual_shader->get_node(get_current_shader_type(), node_id);
5433
if (vsnode.is_null()) {
5434
return;
5435
}
5436
vsnode->set_size(p_new_rect.size / graph->get_zoom());
5437
}
5438
5439
void VisualShaderEditor::_dup_copy_nodes(int p_type, List<CopyItem> &r_items, List<VisualShader::Connection> &r_connections) {
5440
VisualShader::Type type = (VisualShader::Type)p_type;
5441
5442
selection_center.x = 0.0f;
5443
selection_center.y = 0.0f;
5444
5445
HashSet<int> nodes;
5446
5447
for (int i = 0; i < graph->get_child_count(); i++) {
5448
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
5449
if (graph_element) {
5450
int id = String(graph_element->get_name()).to_int();
5451
5452
Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
5453
Ref<VisualShaderNodeOutput> output = node;
5454
if (output.is_valid()) { // can't duplicate output
5455
continue;
5456
}
5457
5458
if (node.is_valid() && graph_element->is_selected()) {
5459
Vector2 pos = visual_shader->get_node_position(type, id);
5460
selection_center += pos;
5461
5462
CopyItem item;
5463
item.id = id;
5464
item.node = visual_shader->get_node(type, id)->duplicate();
5465
item.position = visual_shader->get_node_position(type, id);
5466
5467
Ref<VisualShaderNodeResizableBase> resizable_base = node;
5468
if (resizable_base.is_valid()) {
5469
item.size = resizable_base->get_size();
5470
}
5471
5472
Ref<VisualShaderNodeGroupBase> group = node;
5473
if (group.is_valid()) {
5474
item.group_inputs = group->get_inputs();
5475
item.group_outputs = group->get_outputs();
5476
}
5477
5478
Ref<VisualShaderNodeExpression> expression = node;
5479
if (expression.is_valid()) {
5480
item.expression = expression->get_expression();
5481
}
5482
5483
r_items.push_back(item);
5484
5485
nodes.insert(id);
5486
}
5487
}
5488
}
5489
5490
List<VisualShader::Connection> node_connections;
5491
visual_shader->get_node_connections(type, &node_connections);
5492
5493
for (const VisualShader::Connection &E : node_connections) {
5494
if (nodes.has(E.from_node) && nodes.has(E.to_node)) {
5495
r_connections.push_back(E);
5496
}
5497
}
5498
5499
selection_center /= (float)r_items.size();
5500
}
5501
5502
void VisualShaderEditor::_dup_paste_nodes(int p_type, List<CopyItem> &r_items, const List<VisualShader::Connection> &p_connections, const Vector2 &p_offset, bool p_duplicate) {
5503
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5504
if (p_duplicate) {
5505
undo_redo->create_action(TTR("Duplicate VisualShader Node(s)"));
5506
} else {
5507
bool copy_buffer_empty = true;
5508
for (const CopyItem &item : copy_items_buffer) {
5509
if (!item.disabled) {
5510
copy_buffer_empty = false;
5511
break;
5512
}
5513
}
5514
if (copy_buffer_empty) {
5515
return;
5516
}
5517
5518
undo_redo->create_action(TTR("Paste VisualShader Node(s)"));
5519
}
5520
5521
VisualShader::Type type = (VisualShader::Type)p_type;
5522
5523
int base_id = visual_shader->get_valid_node_id(type);
5524
int id_from = base_id;
5525
HashMap<int, int> connection_remap; // Used for connections and frame attachments.
5526
HashSet<int> unsupported_set;
5527
HashSet<int> added_set;
5528
5529
for (CopyItem &item : r_items) {
5530
if (item.disabled) {
5531
unsupported_set.insert(item.id);
5532
continue;
5533
}
5534
connection_remap[item.id] = id_from;
5535
Ref<VisualShaderNode> node = item.node->duplicate();
5536
node->set_frame(-1); // Do not reattach nodes to frame (for now).
5537
5538
Ref<VisualShaderNodeResizableBase> resizable_base = Object::cast_to<VisualShaderNodeResizableBase>(node.ptr());
5539
if (resizable_base.is_valid()) {
5540
undo_redo->add_do_method(node.ptr(), "set_size", item.size);
5541
}
5542
5543
Ref<VisualShaderNodeFrame> frame = Object::cast_to<VisualShaderNodeFrame>(node.ptr());
5544
if (frame.is_valid()) {
5545
// Do not reattach nodes to frame (for now).
5546
undo_redo->add_do_method(node.ptr(), "set_attached_nodes", PackedInt32Array());
5547
}
5548
5549
Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
5550
if (group.is_valid()) {
5551
undo_redo->add_do_method(node.ptr(), "set_inputs", item.group_inputs);
5552
undo_redo->add_do_method(node.ptr(), "set_outputs", item.group_outputs);
5553
}
5554
5555
Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
5556
if (expression.is_valid()) {
5557
undo_redo->add_do_method(node.ptr(), "set_expression", item.expression);
5558
}
5559
5560
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, node, item.position + p_offset, id_from);
5561
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from, false, false);
5562
5563
added_set.insert(id_from);
5564
id_from++;
5565
}
5566
5567
// Attach nodes to frame.
5568
for (const CopyItem &item : r_items) {
5569
Ref<VisualShaderNode> node = item.node;
5570
if (node->get_frame() == -1) {
5571
continue;
5572
}
5573
5574
int new_node_id = connection_remap[item.id];
5575
int new_frame_id = node->get_frame();
5576
5577
if (connection_remap.has(new_frame_id)) {
5578
new_frame_id = connection_remap[new_frame_id];
5579
}
5580
5581
undo_redo->add_do_method(visual_shader.ptr(), "attach_node_to_frame", type, new_node_id, new_frame_id);
5582
undo_redo->add_do_method(graph_plugin.ptr(), "attach_node_to_frame", type, new_node_id, new_frame_id);
5583
}
5584
5585
// Connect nodes.
5586
for (const VisualShader::Connection &E : p_connections) {
5587
if (unsupported_set.has(E.from_node) || unsupported_set.has(E.to_node)) {
5588
continue;
5589
}
5590
5591
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
5592
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
5593
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
5594
}
5595
5596
id_from = base_id;
5597
for (const CopyItem &item : r_items) {
5598
if (item.disabled) {
5599
continue;
5600
}
5601
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
5602
undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from, false);
5603
id_from++;
5604
}
5605
5606
undo_redo->commit_action();
5607
5608
// Reselect nodes by excluding the other ones.
5609
for (int i = 0; i < graph->get_child_count(); i++) {
5610
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
5611
if (graph_element) {
5612
int id = String(graph_element->get_name()).to_int();
5613
if (added_set.has(id)) {
5614
graph_element->set_selected(true);
5615
} else {
5616
graph_element->set_selected(false);
5617
}
5618
}
5619
}
5620
}
5621
5622
void VisualShaderEditor::_clear_copy_buffer() {
5623
copy_items_buffer.clear();
5624
copy_connections_buffer.clear();
5625
}
5626
5627
void VisualShaderEditor::_duplicate_nodes() {
5628
int type = get_current_shader_type();
5629
5630
List<CopyItem> items;
5631
List<VisualShader::Connection> node_connections;
5632
5633
_dup_copy_nodes(type, items, node_connections);
5634
5635
if (items.is_empty()) {
5636
return;
5637
}
5638
5639
_dup_paste_nodes(type, items, node_connections, Vector2(10, 10) * EDSCALE, true);
5640
}
5641
5642
void VisualShaderEditor::_copy_nodes(bool p_cut) {
5643
_clear_copy_buffer();
5644
5645
_dup_copy_nodes(get_current_shader_type(), copy_items_buffer, copy_connections_buffer);
5646
5647
if (p_cut) {
5648
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5649
undo_redo->create_action(TTR("Cut VisualShader Node(s)"));
5650
5651
List<int> ids;
5652
for (const CopyItem &E : copy_items_buffer) {
5653
ids.push_back(E.id);
5654
}
5655
5656
_delete_nodes(get_current_shader_type(), ids);
5657
5658
undo_redo->commit_action();
5659
}
5660
}
5661
5662
void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2 &p_custom_position) {
5663
if (copy_items_buffer.is_empty()) {
5664
return;
5665
}
5666
5667
int type = get_current_shader_type();
5668
5669
float scale = graph->get_zoom();
5670
5671
Vector2 mpos;
5672
if (p_use_custom_position) {
5673
mpos = p_custom_position;
5674
} else {
5675
mpos = graph->get_local_mouse_position();
5676
}
5677
5678
_dup_paste_nodes(type, copy_items_buffer, copy_connections_buffer, graph->get_scroll_offset() / scale + mpos / scale - selection_center, false);
5679
}
5680
5681
void VisualShaderEditor::_type_selected(int p_id) {
5682
int offset = VisualShader::TYPE_VERTEX;
5683
if (mode & MODE_FLAGS_PARTICLES) {
5684
offset = VisualShader::TYPE_START;
5685
if (p_id + offset > VisualShader::TYPE_PROCESS) {
5686
custom_mode_box->set_visible(false);
5687
custom_mode_enabled = false;
5688
} else {
5689
custom_mode_box->set_visible(true);
5690
if (custom_mode_box->is_pressed()) {
5691
custom_mode_enabled = true;
5692
offset += 3;
5693
}
5694
}
5695
} else if (mode & MODE_FLAGS_SKY) {
5696
offset = VisualShader::TYPE_SKY;
5697
} else if (mode & MODE_FLAGS_FOG) {
5698
offset = VisualShader::TYPE_FOG;
5699
} else if (mode & MODE_FLAGS_TEXTURE_BLIT) {
5700
offset = VisualShader::TYPE_TEXTURE_BLIT;
5701
}
5702
5703
set_current_shader_type(VisualShader::Type(p_id + offset));
5704
_update_nodes();
5705
_update_graph();
5706
5707
graph->grab_focus(true);
5708
}
5709
5710
void VisualShaderEditor::_custom_mode_toggled(bool p_enabled) {
5711
if (!(mode & MODE_FLAGS_PARTICLES)) {
5712
return;
5713
}
5714
custom_mode_enabled = p_enabled;
5715
int id = edit_type->get_selected() + 3;
5716
if (p_enabled) {
5717
set_current_shader_type(VisualShader::Type(id + 3));
5718
} else {
5719
set_current_shader_type(VisualShader::Type(id));
5720
}
5721
_update_options_menu();
5722
_update_graph();
5723
}
5724
5725
void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, const String &p_name) {
5726
String prev_name = p_input->get_input_name();
5727
5728
if (p_name == prev_name) {
5729
return;
5730
}
5731
5732
VisualShaderNode::PortType next_input_type = p_input->get_input_type_by_name(p_name);
5733
VisualShaderNode::PortType prev_input_type = p_input->get_input_type_by_name(prev_name);
5734
5735
bool type_changed = next_input_type != prev_input_type;
5736
5737
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5738
undo_redo_man->create_action(TTR("Visual Shader Input Type Changed"));
5739
5740
undo_redo_man->add_do_method(p_input.ptr(), "set_input_name", p_name);
5741
undo_redo_man->add_undo_method(p_input.ptr(), "set_input_name", prev_name);
5742
5743
if (type_changed) {
5744
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5745
VisualShader::Type type = VisualShader::Type(type_id);
5746
5747
int id = visual_shader->find_node_id(type, p_input);
5748
if (id != VisualShader::NODE_ID_INVALID) {
5749
bool is_expanded = p_input->is_output_port_expandable(0) && p_input->_is_output_port_expanded(0);
5750
5751
int type_size = 0;
5752
if (is_expanded) {
5753
switch (next_input_type) {
5754
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
5755
type_size = 2;
5756
} break;
5757
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
5758
type_size = 3;
5759
} break;
5760
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
5761
type_size = 4;
5762
} break;
5763
default:
5764
break;
5765
}
5766
}
5767
5768
List<VisualShader::Connection> conns;
5769
visual_shader->get_node_connections(type, &conns);
5770
for (const VisualShader::Connection &E : conns) {
5771
int cn_from_node = E.from_node;
5772
int cn_from_port = E.from_port;
5773
int cn_to_node = E.to_node;
5774
int cn_to_port = E.to_port;
5775
5776
if (cn_from_node == id) {
5777
bool is_incompatible_types = !visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, cn_to_node)->get_input_port_type(cn_to_port));
5778
5779
if (is_incompatible_types || cn_from_port > type_size) {
5780
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5781
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5782
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5783
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5784
}
5785
}
5786
}
5787
5788
undo_redo_man->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
5789
undo_redo_man->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
5790
}
5791
}
5792
}
5793
5794
undo_redo_man->commit_action();
5795
}
5796
5797
void VisualShaderEditor::_parameter_ref_select_item(Ref<VisualShaderNodeParameterRef> p_parameter_ref, const String &p_name) {
5798
String prev_name = p_parameter_ref->get_parameter_name();
5799
5800
if (p_name == prev_name) {
5801
return;
5802
}
5803
5804
bool type_changed = p_parameter_ref->get_parameter_type_by_name(p_name) != p_parameter_ref->get_parameter_type_by_name(prev_name);
5805
5806
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5807
undo_redo_man->create_action(TTR("ParameterRef Name Changed"));
5808
5809
undo_redo_man->add_do_method(p_parameter_ref.ptr(), "set_parameter_name", p_name);
5810
undo_redo_man->add_undo_method(p_parameter_ref.ptr(), "set_parameter_name", prev_name);
5811
5812
// update output port
5813
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5814
VisualShader::Type type = VisualShader::Type(type_id);
5815
int id = visual_shader->find_node_id(type, p_parameter_ref);
5816
if (id != VisualShader::NODE_ID_INVALID) {
5817
if (type_changed) {
5818
List<VisualShader::Connection> conns;
5819
visual_shader->get_node_connections(type, &conns);
5820
for (const VisualShader::Connection &E : conns) {
5821
if (E.from_node == id) {
5822
if (visual_shader->is_port_types_compatible(p_parameter_ref->get_parameter_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) {
5823
continue;
5824
}
5825
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5826
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5827
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5828
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5829
}
5830
}
5831
}
5832
undo_redo_man->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
5833
undo_redo_man->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
5834
break;
5835
}
5836
}
5837
5838
undo_redo_man->commit_action();
5839
}
5840
5841
void VisualShaderEditor::_varying_select_item(Ref<VisualShaderNodeVarying> p_varying, const String &p_name) {
5842
String prev_name = p_varying->get_varying_name();
5843
5844
if (p_name == prev_name) {
5845
return;
5846
}
5847
5848
bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
5849
5850
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5851
undo_redo_man->create_action(TTR("Varying Name Changed"));
5852
5853
undo_redo_man->add_do_method(p_varying.ptr(), "set_varying_name", p_name);
5854
undo_redo_man->add_undo_method(p_varying.ptr(), "set_varying_name", prev_name);
5855
5856
VisualShader::VaryingType vtype = p_varying->get_varying_type_by_name(p_name);
5857
VisualShader::VaryingType prev_vtype = p_varying->get_varying_type_by_name(prev_name);
5858
5859
bool type_changed = vtype != prev_vtype;
5860
5861
if (type_changed) {
5862
undo_redo_man->add_do_method(p_varying.ptr(), "set_varying_type", vtype);
5863
undo_redo_man->add_undo_method(p_varying.ptr(), "set_varying_type", prev_vtype);
5864
}
5865
5866
// update ports
5867
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5868
VisualShader::Type type = VisualShader::Type(type_id);
5869
int id = visual_shader->find_node_id(type, p_varying);
5870
5871
if (id != VisualShader::NODE_ID_INVALID) {
5872
if (type_changed) {
5873
List<VisualShader::Connection> conns;
5874
visual_shader->get_node_connections(type, &conns);
5875
5876
for (const VisualShader::Connection &E : conns) {
5877
if (is_getter) {
5878
if (E.from_node == id) {
5879
if (visual_shader->is_port_types_compatible(p_varying->get_varying_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) {
5880
continue;
5881
}
5882
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5883
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5884
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5885
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5886
}
5887
} else {
5888
if (E.to_node == id) {
5889
if (visual_shader->is_port_types_compatible(p_varying->get_varying_type_by_name(p_name), visual_shader->get_node(type, E.from_node)->get_output_port_type(E.from_port))) {
5890
continue;
5891
}
5892
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5893
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5894
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5895
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5896
}
5897
}
5898
}
5899
}
5900
5901
undo_redo_man->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
5902
undo_redo_man->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
5903
break;
5904
}
5905
}
5906
5907
undo_redo_man->commit_action();
5908
}
5909
5910
void VisualShaderEditor::_float_constant_selected(int p_which) {
5911
ERR_FAIL_INDEX(p_which, MAX_FLOAT_CONST_DEFS);
5912
5913
VisualShader::Type type = get_current_shader_type();
5914
Ref<VisualShaderNodeFloatConstant> node = visual_shader->get_node(type, selected_float_constant);
5915
ERR_FAIL_COND(node.is_null());
5916
5917
if (Math::is_equal_approx(node->get_constant(), float_constant_defs[p_which].value)) {
5918
return; // same
5919
}
5920
5921
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5922
undo_redo->create_action(vformat(TTR("Set Constant: %s"), float_constant_defs[p_which].name));
5923
undo_redo->add_do_method(node.ptr(), "set_constant", float_constant_defs[p_which].value);
5924
undo_redo->add_undo_method(node.ptr(), "set_constant", node->get_constant());
5925
undo_redo->commit_action();
5926
}
5927
5928
void VisualShaderEditor::_member_filter_changed(const String &p_text) {
5929
_update_options_menu();
5930
}
5931
5932
void VisualShaderEditor::_member_selected() {
5933
TreeItem *item = members->get_selected();
5934
5935
if (item != nullptr && item->has_meta("id")) {
5936
members_dialog->get_ok_button()->set_disabled(false);
5937
highend_label->set_visible(add_options[item->get_meta("id")].highend);
5938
node_desc->set_text(_get_description(item->get_meta("id")));
5939
} else {
5940
highend_label->set_visible(false);
5941
members_dialog->get_ok_button()->set_disabled(true);
5942
node_desc->set_text("");
5943
}
5944
}
5945
5946
void VisualShaderEditor::_member_create() {
5947
TreeItem *item = members->get_selected();
5948
if (item != nullptr && item->has_meta("id")) {
5949
int idx = members->get_selected()->get_meta("id");
5950
if (connection_node_insert_requested) {
5951
from_node = String(clicked_connection->from_node).to_int();
5952
from_slot = clicked_connection->from_port;
5953
to_node = String(clicked_connection->to_node).to_int();
5954
to_slot = clicked_connection->to_port;
5955
5956
connection_node_insert_requested = false;
5957
5958
saved_node_pos_dirty = true;
5959
5960
// Find both graph nodes and get their positions.
5961
GraphNode *from_graph_element = Object::cast_to<GraphNode>(graph->get_node(itos(from_node)));
5962
GraphNode *to_graph_element = Object::cast_to<GraphNode>(graph->get_node(itos(to_node)));
5963
5964
ERR_FAIL_NULL(from_graph_element);
5965
ERR_FAIL_NULL(to_graph_element);
5966
5967
// Since the size of the node to add is not known yet, it's not possible to center it exactly.
5968
float zoom = graph->get_zoom();
5969
saved_node_pos = 0.5 * (from_graph_element->get_position() + zoom * from_graph_element->get_output_port_position(from_slot) + to_graph_element->get_position() + zoom * to_graph_element->get_input_port_position(to_slot));
5970
}
5971
_add_node(idx, add_options[idx].ops);
5972
members_dialog->hide();
5973
}
5974
}
5975
5976
void VisualShaderEditor::_member_cancel() {
5977
to_node = -1;
5978
to_slot = -1;
5979
from_node = -1;
5980
from_slot = -1;
5981
connection_node_insert_requested = false;
5982
}
5983
5984
void VisualShaderEditor::_update_varying_tree() {
5985
varyings->clear();
5986
TreeItem *root = varyings->create_item();
5987
5988
int count = visual_shader->get_varyings_count();
5989
5990
for (int i = 0; i < count; i++) {
5991
const VisualShader::Varying *varying = visual_shader->get_varying_by_index(i);
5992
5993
if (varying) {
5994
TreeItem *item = varyings->create_item(root);
5995
item->set_text(0, varying->name);
5996
5997
if (i == 0) {
5998
item->select(0);
5999
}
6000
6001
switch (varying->type) {
6002
case VisualShader::VARYING_TYPE_FLOAT:
6003
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)));
6004
break;
6005
case VisualShader::VARYING_TYPE_INT:
6006
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)));
6007
break;
6008
case VisualShader::VARYING_TYPE_UINT:
6009
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)));
6010
break;
6011
case VisualShader::VARYING_TYPE_VECTOR_2D:
6012
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)));
6013
break;
6014
case VisualShader::VARYING_TYPE_VECTOR_3D:
6015
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)));
6016
break;
6017
case VisualShader::VARYING_TYPE_VECTOR_4D:
6018
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)));
6019
break;
6020
case VisualShader::VARYING_TYPE_BOOLEAN:
6021
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)));
6022
break;
6023
case VisualShader::VARYING_TYPE_TRANSFORM:
6024
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)));
6025
break;
6026
default:
6027
break;
6028
}
6029
}
6030
}
6031
6032
varying_button->get_popup()->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
6033
}
6034
6035
void VisualShaderEditor::_varying_create() {
6036
_add_varying(varying_name->get_text(), (VisualShader::VaryingMode)varying_mode->get_selected(), (VisualShader::VaryingType)varying_type->get_selected());
6037
add_varying_dialog->hide();
6038
}
6039
6040
void VisualShaderEditor::_varying_validate() {
6041
bool has_error = false;
6042
String error;
6043
String varname = varying_name->get_text();
6044
6045
if (!varname.is_valid_ascii_identifier()) {
6046
error += TTR("Invalid name for varying.");
6047
has_error = true;
6048
} else if (visual_shader->has_varying(varname)) {
6049
error += TTR("Varying with that name already exists.");
6050
has_error = true;
6051
}
6052
6053
if (varying_type->get_selected() == 6 && varying_mode->get_selected() == VisualShader::VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) {
6054
if (has_error) {
6055
error += "\n";
6056
}
6057
error += vformat(TTR("Boolean type cannot be used with `%s` varying mode."), U"Vertex → [Fragment, Light]");
6058
has_error = true;
6059
}
6060
6061
if (has_error) {
6062
varying_error_label->show();
6063
varying_error_label->set_text(error);
6064
add_varying_dialog->get_ok_button()->set_disabled(true);
6065
} else {
6066
varying_error_label->hide();
6067
varying_error_label->set_text("");
6068
add_varying_dialog->get_ok_button()->set_disabled(false);
6069
}
6070
add_varying_dialog->reset_size();
6071
}
6072
6073
void VisualShaderEditor::_varying_type_changed(int p_index) {
6074
_varying_validate();
6075
}
6076
6077
void VisualShaderEditor::_varying_mode_changed(int p_index) {
6078
_varying_validate();
6079
}
6080
6081
void VisualShaderEditor::_varying_name_changed(const String &p_name) {
6082
_varying_validate();
6083
}
6084
6085
void VisualShaderEditor::_varying_deleted() {
6086
TreeItem *item = varyings->get_selected();
6087
6088
if (item != nullptr) {
6089
_remove_varying(item->get_text(0));
6090
remove_varying_dialog->hide();
6091
}
6092
}
6093
6094
void VisualShaderEditor::_varying_selected() {
6095
add_varying_dialog->get_ok_button()->set_disabled(false);
6096
}
6097
6098
void VisualShaderEditor::_varying_unselected() {
6099
add_varying_dialog->get_ok_button()->set_disabled(true);
6100
}
6101
6102
void VisualShaderEditor::_tools_menu_option(int p_idx) {
6103
TreeItem *category = members->get_root()->get_first_child();
6104
6105
switch (p_idx) {
6106
case EXPAND_ALL:
6107
6108
while (category) {
6109
category->set_collapsed(false);
6110
TreeItem *sub_category = category->get_first_child();
6111
while (sub_category) {
6112
sub_category->set_collapsed(false);
6113
sub_category = sub_category->get_next();
6114
}
6115
category = category->get_next();
6116
}
6117
6118
break;
6119
6120
case COLLAPSE_ALL:
6121
6122
while (category) {
6123
category->set_collapsed(true);
6124
TreeItem *sub_category = category->get_first_child();
6125
while (sub_category) {
6126
sub_category->set_collapsed(true);
6127
sub_category = sub_category->get_next();
6128
}
6129
category = category->get_next();
6130
}
6131
6132
break;
6133
default:
6134
break;
6135
}
6136
}
6137
6138
void VisualShaderEditor::_node_menu_id_pressed(int p_idx) {
6139
switch (p_idx) {
6140
case NodeMenuOptions::ADD:
6141
_show_members_dialog(true);
6142
break;
6143
case NodeMenuOptions::CUT:
6144
_copy_nodes(true);
6145
break;
6146
case NodeMenuOptions::COPY:
6147
_copy_nodes(false);
6148
break;
6149
case NodeMenuOptions::PASTE:
6150
_paste_nodes(true, menu_point);
6151
break;
6152
case NodeMenuOptions::DELETE_:
6153
_delete_nodes_request(TypedArray<StringName>());
6154
break;
6155
case NodeMenuOptions::DUPLICATE:
6156
_duplicate_nodes();
6157
break;
6158
case NodeMenuOptions::CLEAR_COPY_BUFFER:
6159
_clear_copy_buffer();
6160
break;
6161
case NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS:
6162
_convert_constants_to_parameters(false);
6163
break;
6164
case NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS:
6165
_convert_constants_to_parameters(true);
6166
break;
6167
case NodeMenuOptions::UNLINK_FROM_PARENT_FRAME:
6168
_detach_nodes_from_frame_request();
6169
break;
6170
case NodeMenuOptions::SET_FRAME_TITLE:
6171
_frame_title_popup_show(get_screen_position() + get_local_mouse_position(), selected_frame);
6172
break;
6173
case NodeMenuOptions::ENABLE_FRAME_COLOR:
6174
_frame_color_enabled_changed(selected_frame);
6175
break;
6176
case NodeMenuOptions::SET_FRAME_COLOR:
6177
_frame_color_popup_show(get_screen_position() + get_local_mouse_position(), selected_frame);
6178
break;
6179
case NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK:
6180
_frame_autoshrink_enabled_changed(selected_frame);
6181
break;
6182
default:
6183
break;
6184
}
6185
}
6186
6187
void VisualShaderEditor::_connection_menu_id_pressed(int p_idx) {
6188
switch (p_idx) {
6189
case ConnectionMenuOptions::DISCONNECT: {
6190
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
6191
undo_redo->create_action(TTR("Disconnect"));
6192
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", get_current_shader_type(), String(clicked_connection->from_node).to_int(), clicked_connection->from_port, String(clicked_connection->to_node).to_int(), clicked_connection->to_port);
6193
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", get_current_shader_type(), String(clicked_connection->from_node).to_int(), clicked_connection->from_port, String(clicked_connection->to_node).to_int(), clicked_connection->to_port);
6194
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", get_current_shader_type(), String(clicked_connection->from_node).to_int(), clicked_connection->from_port, String(clicked_connection->to_node).to_int(), clicked_connection->to_port);
6195
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", get_current_shader_type(), String(clicked_connection->from_node).to_int(), clicked_connection->from_port, String(clicked_connection->to_node).to_int(), clicked_connection->to_port);
6196
undo_redo->commit_action();
6197
} break;
6198
case ConnectionMenuOptions::INSERT_NEW_NODE: {
6199
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
6200
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
6201
Ref<VisualShaderNode> node1 = visual_shader->get_node(get_current_shader_type(), String(clicked_connection->from_node).to_int());
6202
if (node1.is_valid()) {
6203
output_port_type = node1->get_output_port_type(from_slot);
6204
}
6205
Ref<VisualShaderNode> node2 = visual_shader->get_node(get_current_shader_type(), String(clicked_connection->to_node).to_int());
6206
if (node2.is_valid()) {
6207
input_port_type = node2->get_input_port_type(to_slot);
6208
}
6209
6210
connection_node_insert_requested = true;
6211
_show_members_dialog(true, input_port_type, output_port_type);
6212
} break;
6213
case ConnectionMenuOptions::INSERT_NEW_REROUTE: {
6214
from_node = String(clicked_connection->from_node).to_int();
6215
from_slot = clicked_connection->from_port;
6216
to_node = String(clicked_connection->to_node).to_int();
6217
to_slot = clicked_connection->to_port;
6218
6219
// Manual offset to place the port exactly at the mouse position.
6220
saved_node_pos -= Vector2(11 * EDSCALE * graph->get_zoom(), 50 * EDSCALE * graph->get_zoom());
6221
6222
// Find reroute addoptions.
6223
int idx = -1;
6224
for (int i = 0; i < add_options.size(); i++) {
6225
if (add_options[i].name == "Reroute") {
6226
idx = i;
6227
break;
6228
}
6229
}
6230
_add_node(idx, add_options[idx].ops);
6231
} break;
6232
default:
6233
break;
6234
}
6235
}
6236
6237
Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
6238
if (p_point == Vector2(Math::INF, Math::INF)) {
6239
return Variant();
6240
}
6241
6242
if (p_from == members) {
6243
TreeItem *it = members->get_item_at_position(p_point);
6244
if (!it) {
6245
return Variant();
6246
}
6247
if (!it->has_meta("id")) {
6248
return Variant();
6249
}
6250
6251
int id = it->get_meta("id");
6252
AddOption op = add_options[id];
6253
6254
Dictionary d;
6255
d["id"] = id;
6256
6257
Label *label = memnew(Label);
6258
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6259
label->set_text(it->get_text(0));
6260
label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
6261
set_drag_preview(label);
6262
return d;
6263
}
6264
return Variant();
6265
}
6266
6267
bool VisualShaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
6268
if (p_point == Vector2(Math::INF, Math::INF)) {
6269
return false;
6270
}
6271
6272
if (p_from == graph) {
6273
Dictionary d = p_data;
6274
6275
if (d.has("id")) {
6276
return true;
6277
}
6278
if (d.has("files")) {
6279
return true;
6280
}
6281
}
6282
6283
return false;
6284
}
6285
6286
void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
6287
if (p_point == Vector2(Math::INF, Math::INF)) {
6288
return;
6289
}
6290
6291
if (p_from == graph) {
6292
Dictionary d = p_data;
6293
6294
if (d.has("id")) {
6295
int idx = d["id"];
6296
saved_node_pos = p_point;
6297
saved_node_pos_dirty = true;
6298
_add_node(idx, add_options[idx].ops);
6299
} else if (d.has("files")) {
6300
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
6301
undo_redo->create_action(TTR("Add Node(s) to Visual Shader"));
6302
6303
if (d["files"].get_type() == Variant::PACKED_STRING_ARRAY) {
6304
PackedStringArray arr = d["files"];
6305
for (int i = 0; i < arr.size(); i++) {
6306
String type = ResourceLoader::get_resource_type(arr[i]);
6307
if (type == "GDScript") {
6308
Ref<Script> scr = ResourceLoader::load(arr[i]);
6309
if (scr->get_instance_base_type() == "VisualShaderNodeCustom") {
6310
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6311
saved_node_pos_dirty = true;
6312
6313
int idx = -1;
6314
6315
for (int j = custom_node_option_idx; j < add_options.size(); j++) {
6316
if (add_options[j].script.is_valid()) {
6317
if (add_options[j].script->get_path() == arr[i]) {
6318
idx = j;
6319
break;
6320
}
6321
}
6322
}
6323
if (idx != -1) {
6324
_add_node(idx, {}, arr[i], i);
6325
}
6326
}
6327
} else if (type == "CurveTexture") {
6328
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6329
saved_node_pos_dirty = true;
6330
_add_node(curve_node_option_idx, {}, arr[i], i);
6331
} else if (type == "CurveXYZTexture") {
6332
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6333
saved_node_pos_dirty = true;
6334
_add_node(curve_xyz_node_option_idx, {}, arr[i], i);
6335
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
6336
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6337
saved_node_pos_dirty = true;
6338
_add_node(texture2d_node_option_idx, {}, arr[i], i);
6339
} else if (type == "Texture2DArray") {
6340
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6341
saved_node_pos_dirty = true;
6342
_add_node(texture2d_array_node_option_idx, {}, arr[i], i);
6343
} else if (ClassDB::get_parent_class(type) == "Texture3D") {
6344
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6345
saved_node_pos_dirty = true;
6346
_add_node(texture3d_node_option_idx, {}, arr[i], i);
6347
} else if (type == "Cubemap") {
6348
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6349
saved_node_pos_dirty = true;
6350
_add_node(cubemap_node_option_idx, {}, arr[i], i);
6351
} else if (type == "Mesh" && visual_shader->get_mode() == Shader::MODE_PARTICLES &&
6352
(get_current_shader_type() == VisualShader::TYPE_START || get_current_shader_type() == VisualShader::TYPE_START_CUSTOM)) {
6353
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6354
saved_node_pos_dirty = true;
6355
_add_node(mesh_emitter_option_idx, {}, arr[i], i);
6356
}
6357
}
6358
}
6359
undo_redo->commit_action();
6360
}
6361
}
6362
}
6363
6364
void VisualShaderEditor::_show_preview_text() {
6365
code_preview_showed = !code_preview_showed;
6366
if (code_preview_showed) {
6367
if (code_preview_first) {
6368
code_preview_window->set_size(Size2(400 * EDSCALE, 600 * EDSCALE));
6369
code_preview_window->popup_centered();
6370
code_preview_first = false;
6371
} else {
6372
code_preview_window->popup();
6373
}
6374
6375
if (pending_update_preview) {
6376
_update_preview();
6377
pending_update_preview = false;
6378
}
6379
} else {
6380
code_preview_window->hide();
6381
}
6382
}
6383
6384
void VisualShaderEditor::_preview_close_requested() {
6385
code_preview_showed = false;
6386
code_preview_button->set_pressed(false);
6387
}
6388
6389
static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_type(const StringName &p_variable) {
6390
RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_variable);
6391
return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
6392
}
6393
6394
void VisualShaderEditor::_update_preview() {
6395
if (!code_preview_showed) {
6396
pending_update_preview = true;
6397
return;
6398
}
6399
6400
String code = visual_shader->get_code();
6401
6402
preview_text->set_text(code);
6403
6404
ShaderLanguage::ShaderCompileInfo info;
6405
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
6406
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
6407
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
6408
info.shader_types = ShaderTypes::get_singleton()->get_types();
6409
info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type;
6410
6411
for (int i = 0; i < preview_text->get_line_count(); i++) {
6412
preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
6413
}
6414
6415
String preprocessed_code;
6416
{
6417
String path = visual_shader->get_path();
6418
String error_pp;
6419
List<ShaderPreprocessor::FilePosition> err_positions;
6420
ShaderPreprocessor preprocessor;
6421
Error err = preprocessor.preprocess(code, path, preprocessed_code, &error_pp, &err_positions);
6422
if (err != OK) {
6423
ERR_FAIL_COND(err_positions.is_empty());
6424
6425
String file = err_positions.front()->get().file;
6426
int err_line = err_positions.front()->get().line;
6427
Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
6428
preview_text->set_line_background_color(err_line - 1, error_line_color);
6429
error_panel->show();
6430
6431
error_label->set_text("error(" + file + ":" + itos(err_line) + "): " + error_pp);
6432
shader_error = true;
6433
return;
6434
}
6435
}
6436
6437
ShaderLanguage sl;
6438
Error err = sl.compile(preprocessed_code, info);
6439
if (err != OK) {
6440
int err_line;
6441
String err_text;
6442
Vector<ShaderLanguage::FilePosition> include_positions = sl.get_include_positions();
6443
if (include_positions.size() > 1) {
6444
// Error is in an include.
6445
err_line = include_positions[0].line;
6446
err_text = "error(" + itos(err_line) + ") in include " + include_positions[include_positions.size() - 1].file + ":" + itos(include_positions[include_positions.size() - 1].line) + ": " + sl.get_error_text();
6447
} else {
6448
err_line = sl.get_error_line();
6449
err_text = "error(" + itos(err_line) + "): " + sl.get_error_text();
6450
}
6451
6452
Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
6453
preview_text->set_line_background_color(err_line - 1, error_line_color);
6454
error_panel->show();
6455
6456
error_label->set_text(err_text);
6457
shader_error = true;
6458
} else {
6459
error_panel->hide();
6460
shader_error = false;
6461
}
6462
}
6463
6464
void VisualShaderEditor::_update_next_previews(int p_node_id) {
6465
VisualShader::Type type = get_current_shader_type();
6466
6467
LocalVector<int> nodes;
6468
_get_next_nodes_recursively(type, p_node_id, nodes);
6469
6470
for (int node_id : nodes) {
6471
if (graph_plugin->is_preview_visible(node_id)) {
6472
graph_plugin->update_node_deferred(type, node_id);
6473
}
6474
}
6475
}
6476
6477
void VisualShaderEditor::_get_next_nodes_recursively(VisualShader::Type p_type, int p_node_id, LocalVector<int> &r_nodes) const {
6478
const LocalVector<int> &next_connections = visual_shader->get_next_connected_nodes(p_type, p_node_id);
6479
6480
for (int node_id : next_connections) {
6481
r_nodes.push_back(node_id);
6482
_get_next_nodes_recursively(p_type, node_id, r_nodes);
6483
}
6484
}
6485
6486
void VisualShaderEditor::_visibility_changed() {
6487
if (!is_visible()) {
6488
if (code_preview_window->is_visible()) {
6489
code_preview_button->set_pressed(false);
6490
code_preview_window->hide();
6491
code_preview_showed = false;
6492
}
6493
}
6494
}
6495
6496
void VisualShaderEditor::_show_shader_preview() {
6497
shader_preview_showed = !shader_preview_showed;
6498
if (shader_preview_showed) {
6499
shader_preview_vbox->show();
6500
} else {
6501
shader_preview_vbox->hide();
6502
6503
_param_unselected();
6504
}
6505
}
6506
6507
void VisualShaderEditor::set_toggle_list_control(Control *p_toggle_list_control) {
6508
toggle_files_list = p_toggle_list_control;
6509
}
6510
6511
void VisualShaderEditor::_toggle_files_pressed() {
6512
ERR_FAIL_NULL(toggle_files_list);
6513
toggle_files_list->set_visible(!toggle_files_list->is_visible());
6514
update_toggle_files_button();
6515
}
6516
6517
void VisualShaderEditor::_bind_methods() {
6518
ClassDB::bind_method("_update_nodes", &VisualShaderEditor::_update_nodes);
6519
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
6520
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
6521
ClassDB::bind_method("_parameter_ref_select_item", &VisualShaderEditor::_parameter_ref_select_item);
6522
ClassDB::bind_method("_varying_select_item", &VisualShaderEditor::_varying_select_item);
6523
ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size);
6524
ClassDB::bind_method("_update_parameters", &VisualShaderEditor::_update_parameters);
6525
ClassDB::bind_method("_update_varyings", &VisualShaderEditor::_update_varyings);
6526
ClassDB::bind_method("_update_varying_tree", &VisualShaderEditor::_update_varying_tree);
6527
ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode);
6528
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
6529
ClassDB::bind_method("_update_parameter", &VisualShaderEditor::_update_parameter);
6530
ClassDB::bind_method("_update_next_previews", &VisualShaderEditor::_update_next_previews);
6531
ClassDB::bind_method("_update_current_param", &VisualShaderEditor::_update_current_param);
6532
}
6533
6534
VisualShaderEditor::VisualShaderEditor() {
6535
vs_editor_cache.instantiate();
6536
vs_editor_cache->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
6537
6538
ShaderLanguage::get_keyword_list(&keyword_list);
6539
EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &VisualShaderEditor::_resource_saved));
6540
FileSystemDock::get_singleton()->get_script_create_dialog()->connect("script_created", callable_mp(this, &VisualShaderEditor::_script_created));
6541
FileSystemDock::get_singleton()->connect("resource_removed", callable_mp(this, &VisualShaderEditor::_resource_removed));
6542
6543
HSplitContainer *main_box = memnew(HSplitContainer);
6544
main_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
6545
add_child(main_box);
6546
6547
graph = memnew(GraphEdit);
6548
graph->set_v_size_flags(SIZE_EXPAND_FILL);
6549
graph->set_h_size_flags(SIZE_EXPAND_FILL);
6550
graph->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
6551
graph->set_grid_pattern(GraphEdit::GridPattern::GRID_PATTERN_DOTS);
6552
int grid_pattern = EDITOR_GET("editors/visual_editors/grid_pattern");
6553
graph->set_grid_pattern((GraphEdit::GridPattern)grid_pattern);
6554
graph->set_show_zoom_label(true);
6555
main_box->add_child(graph);
6556
SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor);
6557
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
6558
graph->set_minimap_opacity(graph_minimap_opacity);
6559
float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature");
6560
graph->set_connection_lines_curvature(graph_lines_curvature);
6561
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR);
6562
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR_INT);
6563
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6564
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN);
6565
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_2D);
6566
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_3D);
6567
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_4D);
6568
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM);
6569
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
6570
//graph->add_valid_left_disconnect_type(0);
6571
graph->set_v_size_flags(SIZE_EXPAND_FILL);
6572
graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), CONNECT_DEFERRED);
6573
graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), CONNECT_DEFERRED);
6574
graph->connect("node_selected", callable_mp(this, &VisualShaderEditor::_node_selected));
6575
graph->connect("scroll_offset_changed", callable_mp(this, &VisualShaderEditor::_scroll_offset_changed));
6576
graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes));
6577
graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(false));
6578
graph->connect("cut_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(true));
6579
graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes).bind(false, Point2()));
6580
graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request));
6581
graph->connect(SceneStringName(gui_input), callable_mp(this, &VisualShaderEditor::_graph_gui_input));
6582
graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty));
6583
graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty));
6584
graph->connect("connection_drag_ended", callable_mp(this, &VisualShaderEditor::_connection_drag_ended));
6585
graph->connect(SceneStringName(visibility_changed), callable_mp(this, &VisualShaderEditor::_visibility_changed));
6586
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
6587
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6588
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6589
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6590
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6591
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6592
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
6593
6594
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR);
6595
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6596
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6597
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6598
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6599
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6600
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_BOOLEAN);
6601
6602
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR);
6603
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6604
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6605
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6606
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6607
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6608
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_BOOLEAN);
6609
6610
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR);
6611
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6612
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6613
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6614
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6615
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6616
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6617
6618
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR);
6619
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6620
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6621
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6622
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6623
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6624
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6625
6626
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR);
6627
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6628
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6629
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6630
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6631
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6632
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6633
6634
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR);
6635
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6636
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6637
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6638
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6639
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6640
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN);
6641
6642
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
6643
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
6644
6645
info_label = memnew(Label);
6646
info_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6647
info_label->set_text(vformat(TTR("Hold %s Key To Swap Connections"), keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL)));
6648
info_label->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_WIDE, PRESET_MODE_MINSIZE, 20);
6649
info_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
6650
info_label->hide();
6651
graph->get_top_layer()->add_child(info_label);
6652
6653
PanelContainer *toolbar_panel = static_cast<PanelContainer *>(graph->get_menu_hbox()->get_parent());
6654
toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10);
6655
toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
6656
6657
toolbar_hflow = memnew(HFlowContainer);
6658
{
6659
LocalVector<Node *> nodes;
6660
for (int i = 0; i < graph->get_menu_hbox()->get_child_count(); i++) {
6661
Node *child = graph->get_menu_hbox()->get_child(i);
6662
nodes.push_back(child);
6663
}
6664
6665
for (Node *node : nodes) {
6666
graph->get_menu_hbox()->remove_child(node);
6667
toolbar_hflow->add_child(node);
6668
}
6669
6670
graph->get_menu_hbox()->hide();
6671
toolbar_panel->add_child(toolbar_hflow);
6672
}
6673
6674
VSeparator *vs = memnew(VSeparator);
6675
toolbar_hflow->add_child(vs);
6676
toolbar_hflow->move_child(vs, 0);
6677
6678
custom_mode_box = memnew(CheckBox);
6679
custom_mode_box->set_text(TTR("Custom"));
6680
custom_mode_box->set_pressed(false);
6681
custom_mode_box->set_visible(false);
6682
custom_mode_box->connect(SceneStringName(toggled), callable_mp(this, &VisualShaderEditor::_custom_mode_toggled));
6683
6684
edit_type_standard = memnew(OptionButton);
6685
edit_type_standard->add_item(TTR("Vertex"));
6686
edit_type_standard->add_item(TTR("Fragment"));
6687
edit_type_standard->add_item(TTR("Light"));
6688
edit_type_standard->select(1);
6689
edit_type_standard->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6690
6691
edit_type_particles = memnew(OptionButton);
6692
edit_type_particles->add_item(TTR("Start"));
6693
edit_type_particles->add_item(TTR("Process"));
6694
edit_type_particles->add_item(TTR("Collide"));
6695
edit_type_particles->select(0);
6696
edit_type_particles->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6697
6698
edit_type_sky = memnew(OptionButton);
6699
edit_type_sky->add_item(TTR("Sky"));
6700
edit_type_sky->select(0);
6701
edit_type_sky->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6702
6703
edit_type_fog = memnew(OptionButton);
6704
edit_type_fog->add_item(TTR("Fog"));
6705
edit_type_fog->select(0);
6706
edit_type_fog->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6707
6708
edit_type_texture_blit = memnew(OptionButton);
6709
edit_type_texture_blit->add_item(TTR("Blit"));
6710
edit_type_texture_blit->select(0);
6711
edit_type_texture_blit->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6712
6713
edit_type = edit_type_standard;
6714
6715
toolbar_hflow->add_child(custom_mode_box);
6716
toolbar_hflow->move_child(custom_mode_box, 0);
6717
toolbar_hflow->add_child(edit_type_standard);
6718
toolbar_hflow->move_child(edit_type_standard, 0);
6719
toolbar_hflow->add_child(edit_type_particles);
6720
toolbar_hflow->move_child(edit_type_particles, 0);
6721
toolbar_hflow->add_child(edit_type_sky);
6722
toolbar_hflow->move_child(edit_type_sky, 0);
6723
toolbar_hflow->add_child(edit_type_fog);
6724
toolbar_hflow->move_child(edit_type_fog, 0);
6725
toolbar_hflow->add_child(edit_type_texture_blit);
6726
toolbar_hflow->move_child(edit_type_texture_blit, 0);
6727
6728
add_node = memnew(Button);
6729
add_node->set_theme_type_variation(SceneStringName(FlatButton));
6730
add_node->set_text(TTR("Add Node..."));
6731
toolbar_hflow->add_child(add_node);
6732
toolbar_hflow->move_child(add_node, 0);
6733
add_node->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
6734
6735
graph->connect("graph_elements_linked_to_frame_request", callable_mp(this, &VisualShaderEditor::_nodes_linked_to_frame_request));
6736
graph->connect("frame_rect_changed", callable_mp(this, &VisualShaderEditor::_frame_rect_changed));
6737
6738
varying_button = memnew(MenuButton);
6739
varying_button->set_flat(false);
6740
varying_button->set_theme_type_variation("FlatMenuButton");
6741
varying_button->set_text(TTR("Manage Varyings"));
6742
varying_button->set_switch_on_hover(true);
6743
toolbar_hflow->add_child(varying_button);
6744
6745
PopupMenu *varying_menu = varying_button->get_popup();
6746
varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
6747
varying_menu->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
6748
varying_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
6749
6750
code_preview_button = memnew(Button);
6751
code_preview_button->set_theme_type_variation(SceneStringName(FlatButton));
6752
code_preview_button->set_toggle_mode(true);
6753
code_preview_button->set_tooltip_text(TTR("Show generated shader code."));
6754
toolbar_hflow->add_child(code_preview_button);
6755
code_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_preview_text));
6756
6757
shader_preview_button = memnew(Button);
6758
shader_preview_button->set_theme_type_variation(SceneStringName(FlatButton));
6759
shader_preview_button->set_toggle_mode(true);
6760
shader_preview_button->set_tooltip_text(TTR("Toggle shader preview."));
6761
shader_preview_button->set_pressed(true);
6762
toolbar_hflow->add_child(shader_preview_button);
6763
shader_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_shader_preview));
6764
6765
Control *spacer = memnew(Control);
6766
spacer->set_h_size_flags(Control::SIZE_EXPAND);
6767
toolbar_hflow->add_child(spacer);
6768
6769
site_search = memnew(Button);
6770
site_search->set_theme_type_variation(SceneStringName(FlatButton));
6771
site_search->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_help_open));
6772
site_search->set_text(TTR("Online Docs"));
6773
site_search->set_tooltip_text(TTR("Open Godot online documentation."));
6774
toolbar_hflow->add_child(site_search);
6775
6776
VSeparator *separator = memnew(VSeparator);
6777
toolbar_hflow->add_child(separator);
6778
toolbar_hflow->move_child(separator, 0);
6779
6780
separator = memnew(VSeparator);
6781
toolbar_hflow->add_child(separator);
6782
toolbar_hflow->move_child(separator, 0);
6783
6784
toggle_files_button = memnew(Button);
6785
toggle_files_button->set_theme_type_variation(SceneStringName(FlatButton));
6786
toggle_files_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_toggle_files_pressed));
6787
toolbar_hflow->add_child(toggle_files_button);
6788
toolbar_hflow->move_child(toggle_files_button, 0);
6789
6790
///////////////////////////////////////
6791
// CODE PREVIEW
6792
///////////////////////////////////////
6793
6794
code_preview_window = memnew(AcceptDialog);
6795
code_preview_window->set_title(TTR("Generated Shader Code"));
6796
code_preview_window->set_visible(code_preview_showed);
6797
code_preview_window->set_ok_button_text(TTR("Close"));
6798
code_preview_window->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_preview_close_requested));
6799
code_preview_window->connect("canceled", callable_mp(this, &VisualShaderEditor::_preview_close_requested));
6800
add_child(code_preview_window);
6801
6802
code_preview_vbox = memnew(VBoxContainer);
6803
code_preview_window->add_child(code_preview_vbox);
6804
code_preview_vbox->add_theme_constant_override("separation", 0);
6805
6806
preview_text = memnew(CodeEdit);
6807
syntax_highlighter.instantiate();
6808
code_preview_vbox->add_child(preview_text);
6809
preview_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6810
preview_text->set_syntax_highlighter(syntax_highlighter);
6811
preview_text->set_draw_line_numbers(true);
6812
preview_text->set_editable(false);
6813
6814
error_panel = memnew(PanelContainer);
6815
code_preview_vbox->add_child(error_panel);
6816
error_panel->set_visible(false);
6817
6818
error_label = memnew(Label);
6819
error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6820
error_panel->add_child(error_label);
6821
error_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
6822
6823
///////////////////////////////////////
6824
// POPUP MENU
6825
///////////////////////////////////////
6826
6827
popup_menu = memnew(PopupMenu);
6828
add_child(popup_menu);
6829
popup_menu->set_hide_on_checkable_item_selection(false);
6830
popup_menu->add_item(TTR("Add Node"), NodeMenuOptions::ADD);
6831
popup_menu->add_separator();
6832
popup_menu->add_item(TTR("Cut"), NodeMenuOptions::CUT);
6833
popup_menu->add_item(TTR("Copy"), NodeMenuOptions::COPY);
6834
popup_menu->add_item(TTR("Paste"), NodeMenuOptions::PASTE);
6835
popup_menu->add_item(TTR("Delete"), NodeMenuOptions::DELETE_);
6836
popup_menu->add_item(TTR("Duplicate"), NodeMenuOptions::DUPLICATE);
6837
popup_menu->add_item(TTR("Clear Copy Buffer"), NodeMenuOptions::CLEAR_COPY_BUFFER);
6838
popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_node_menu_id_pressed));
6839
6840
connection_popup_menu = memnew(PopupMenu);
6841
add_child(connection_popup_menu);
6842
connection_popup_menu->add_item(TTR("Disconnect"), ConnectionMenuOptions::DISCONNECT);
6843
connection_popup_menu->add_item(TTR("Insert New Node"), ConnectionMenuOptions::INSERT_NEW_NODE);
6844
connection_popup_menu->add_item(TTR("Insert New Reroute"), ConnectionMenuOptions::INSERT_NEW_REROUTE);
6845
connection_popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_connection_menu_id_pressed));
6846
6847
///////////////////////////////////////
6848
// SHADER PREVIEW
6849
///////////////////////////////////////
6850
6851
shader_preview_vbox = memnew(VBoxContainer);
6852
shader_preview_vbox->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
6853
main_box->add_child(shader_preview_vbox);
6854
6855
VSplitContainer *preview_split = memnew(VSplitContainer);
6856
preview_split->set_v_size_flags(SIZE_EXPAND_FILL);
6857
shader_preview_vbox->add_child(preview_split);
6858
6859
// Initialize material editor.
6860
{
6861
env.instantiate();
6862
Ref<Sky> sky = memnew(Sky());
6863
env->set_sky(sky);
6864
env->set_background(Environment::BG_COLOR);
6865
env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY);
6866
env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY);
6867
6868
preview_material.instantiate();
6869
preview_material->connect(CoreStringName(property_list_changed), callable_mp(this, &VisualShaderEditor::_update_preview_parameter_list));
6870
6871
material_editor = memnew(MaterialEditor);
6872
preview_split->add_child(material_editor);
6873
}
6874
6875
VBoxContainer *params_vbox = memnew(VBoxContainer);
6876
preview_split->add_child(params_vbox);
6877
6878
HBoxContainer *filter_hbox = memnew(HBoxContainer);
6879
params_vbox->add_child(filter_hbox);
6880
6881
param_filter = memnew(LineEdit);
6882
filter_hbox->add_child(param_filter);
6883
param_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_param_filter_changed));
6884
param_filter->set_h_size_flags(SIZE_EXPAND_FILL);
6885
param_filter->set_placeholder(TTR("Filter Parameters"));
6886
6887
preview_tools = memnew(MenuButton);
6888
filter_hbox->add_child(preview_tools);
6889
preview_tools->set_tooltip_text(TTR("Options"));
6890
preview_tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_preview_tools_menu_option));
6891
preview_tools->get_popup()->add_item(TTR("Copy Parameters From Material"), COPY_PARAMS_FROM_MATERIAL);
6892
preview_tools->get_popup()->add_item(TTR("Paste Parameters To Material"), PASTE_PARAMS_TO_MATERIAL);
6893
6894
ScrollContainer *sc = memnew(ScrollContainer);
6895
sc->set_v_size_flags(SIZE_EXPAND_FILL);
6896
params_vbox->add_child(sc);
6897
6898
parameters = memnew(Tree);
6899
parameters->set_hide_root(true);
6900
parameters->set_allow_reselect(true);
6901
parameters->set_hide_folding(false);
6902
parameters->set_h_size_flags(SIZE_EXPAND_FILL);
6903
parameters->set_v_size_flags(SIZE_EXPAND_FILL);
6904
parameters->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
6905
parameters->set_theme_type_variation("TreeSecondary");
6906
parameters->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_param_selected));
6907
parameters->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_param_unselected));
6908
sc->add_child(parameters);
6909
6910
param_vbox = memnew(VBoxContainer);
6911
param_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
6912
param_vbox->hide();
6913
params_vbox->add_child(param_vbox);
6914
6915
ScrollContainer *sc2 = memnew(ScrollContainer);
6916
sc2->set_v_size_flags(SIZE_EXPAND_FILL);
6917
param_vbox->add_child(sc2);
6918
6919
param_vbox2 = memnew(VBoxContainer);
6920
param_vbox2->set_h_size_flags(SIZE_EXPAND_FILL);
6921
sc2->add_child(param_vbox2);
6922
6923
///////////////////////////////////////
6924
// SHADER NODES TREE
6925
///////////////////////////////////////
6926
6927
VBoxContainer *members_vb = memnew(VBoxContainer);
6928
members_vb->set_v_size_flags(SIZE_EXPAND_FILL);
6929
6930
HBoxContainer *filter_hb = memnew(HBoxContainer);
6931
members_vb->add_child(filter_hb);
6932
6933
node_filter = memnew(FilterLineEdit);
6934
filter_hb->add_child(node_filter);
6935
node_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_member_filter_changed));
6936
node_filter->set_h_size_flags(SIZE_EXPAND_FILL);
6937
node_filter->set_placeholder(TTR("Search"));
6938
6939
tools = memnew(MenuButton);
6940
filter_hb->add_child(tools);
6941
tools->set_tooltip_text(TTR("Options"));
6942
tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_tools_menu_option));
6943
tools->get_popup()->add_item(TTR("Expand All"), EXPAND_ALL);
6944
tools->get_popup()->add_item(TTR("Collapse All"), COLLAPSE_ALL);
6945
6946
members = memnew(Tree);
6947
node_filter->set_forward_control(members);
6948
members_vb->add_child(members);
6949
SET_DRAG_FORWARDING_GCD(members, VisualShaderEditor);
6950
members->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
6951
members->set_h_size_flags(SIZE_EXPAND_FILL);
6952
members->set_v_size_flags(SIZE_EXPAND_FILL);
6953
members->set_hide_root(true);
6954
members->set_allow_reselect(true);
6955
members->set_hide_folding(false);
6956
members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
6957
members->connect("item_activated", callable_mp(this, &VisualShaderEditor::_member_create));
6958
members->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_member_selected));
6959
6960
HBoxContainer *desc_hbox = memnew(HBoxContainer);
6961
members_vb->add_child(desc_hbox);
6962
6963
Label *desc_label = memnew(Label);
6964
desc_hbox->add_child(desc_label);
6965
desc_label->set_text(TTR("Description:"));
6966
6967
desc_hbox->add_spacer();
6968
6969
highend_label = memnew(Label);
6970
highend_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6971
desc_hbox->add_child(highend_label);
6972
highend_label->set_visible(false);
6973
highend_label->set_text(TTRC("Forward+/Mobile"));
6974
highend_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
6975
highend_label->set_tooltip_text(TTR("Only supported in the Forward+ and Mobile rendering methods, not Compatibility."));
6976
6977
node_desc = memnew(RichTextLabel);
6978
members_vb->add_child(node_desc);
6979
node_desc->set_h_size_flags(SIZE_EXPAND_FILL);
6980
node_desc->set_v_size_flags(SIZE_FILL);
6981
node_desc->set_custom_minimum_size(Size2(0, 70 * EDSCALE));
6982
6983
members_dialog = memnew(ConfirmationDialog);
6984
members_dialog->set_title(TTR("Create Shader Node"));
6985
members_dialog->add_child(members_vb);
6986
members_dialog->set_ok_button_text(TTR("Create"));
6987
members_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_member_create));
6988
members_dialog->get_ok_button()->set_disabled(true);
6989
members_dialog->connect("canceled", callable_mp(this, &VisualShaderEditor::_member_cancel));
6990
members_dialog->register_text_enter(node_filter);
6991
add_child(members_dialog);
6992
6993
// add varyings dialog
6994
{
6995
add_varying_dialog = memnew(ConfirmationDialog);
6996
add_varying_dialog->set_title(TTR("Create Shader Varying"));
6997
add_varying_dialog->set_ok_button_text(TTR("Create"));
6998
add_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_create));
6999
add_varying_dialog->get_ok_button()->set_disabled(true);
7000
add_child(add_varying_dialog);
7001
7002
VBoxContainer *vb = memnew(VBoxContainer);
7003
add_varying_dialog->add_child(vb);
7004
7005
HBoxContainer *hb = memnew(HBoxContainer);
7006
vb->add_child(hb);
7007
hb->set_h_size_flags(SIZE_EXPAND_FILL);
7008
7009
varying_type = memnew(OptionButton);
7010
hb->add_child(varying_type);
7011
varying_type->add_item("Float");
7012
varying_type->add_item("Int");
7013
varying_type->add_item("UInt");
7014
varying_type->add_item("Vector2");
7015
varying_type->add_item("Vector3");
7016
varying_type->add_item("Vector4");
7017
varying_type->add_item("Boolean");
7018
varying_type->add_item("Transform");
7019
varying_type->set_accessibility_name(TTRC("Varying Type"));
7020
varying_type->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_type_changed));
7021
7022
varying_name = memnew(LineEdit);
7023
hb->add_child(varying_name);
7024
varying_name->set_custom_minimum_size(Size2(150 * EDSCALE, 0));
7025
varying_name->set_h_size_flags(SIZE_EXPAND_FILL);
7026
varying_name->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_varying_name_changed));
7027
add_varying_dialog->register_text_enter(varying_name);
7028
7029
varying_mode = memnew(OptionButton);
7030
hb->add_child(varying_mode);
7031
varying_mode->add_item(U"Vertex → [Fragment, Light]");
7032
varying_mode->add_item(U"Fragment → Light");
7033
varying_mode->set_accessibility_name(TTRC("Varying Mode"));
7034
varying_mode->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_mode_changed));
7035
7036
varying_error_label = memnew(Label);
7037
varying_error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
7038
vb->add_child(varying_error_label);
7039
varying_error_label->set_h_size_flags(SIZE_EXPAND_FILL);
7040
7041
varying_error_label->hide();
7042
}
7043
7044
// remove varying dialog
7045
{
7046
remove_varying_dialog = memnew(ConfirmationDialog);
7047
remove_varying_dialog->set_title(TTR("Delete Shader Varying"));
7048
remove_varying_dialog->set_ok_button_text(TTR("Delete"));
7049
remove_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_deleted));
7050
add_child(remove_varying_dialog);
7051
7052
VBoxContainer *vb = memnew(VBoxContainer);
7053
remove_varying_dialog->add_child(vb);
7054
7055
varyings = memnew(Tree);
7056
vb->add_child(varyings);
7057
varyings->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7058
varyings->set_h_size_flags(SIZE_EXPAND_FILL);
7059
varyings->set_v_size_flags(SIZE_EXPAND_FILL);
7060
varyings->set_hide_root(true);
7061
varyings->set_allow_reselect(true);
7062
varyings->set_hide_folding(false);
7063
varyings->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
7064
varyings->connect("item_activated", callable_mp(this, &VisualShaderEditor::_varying_deleted));
7065
varyings->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_selected));
7066
varyings->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_varying_unselected));
7067
}
7068
7069
alert = memnew(AcceptDialog);
7070
alert->get_label()->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
7071
alert->get_label()->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
7072
alert->get_label()->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
7073
alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE);
7074
add_child(alert);
7075
7076
frame_title_change_popup = memnew(PopupPanel);
7077
frame_title_change_edit = memnew(LineEdit);
7078
frame_title_change_edit->set_expand_to_text_length_enabled(true);
7079
frame_title_change_edit->set_select_all_on_focus(true);
7080
frame_title_change_edit->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_frame_title_text_changed));
7081
frame_title_change_edit->connect(SceneStringName(text_submitted), callable_mp(this, &VisualShaderEditor::_frame_title_text_submitted));
7082
frame_title_change_popup->add_child(frame_title_change_edit);
7083
frame_title_change_edit->reset_size();
7084
frame_title_change_popup->reset_size();
7085
frame_title_change_popup->connect(SceneStringName(focus_exited), callable_mp(this, &VisualShaderEditor::_frame_title_popup_focus_out));
7086
frame_title_change_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_frame_title_popup_hide));
7087
add_child(frame_title_change_popup);
7088
7089
frame_tint_color_pick_popup = memnew(PopupPanel);
7090
VBoxContainer *frame_popup_item_tint_color_editor = memnew(VBoxContainer);
7091
frame_tint_color_pick_popup->add_child(frame_popup_item_tint_color_editor);
7092
frame_tint_color_picker = memnew(ColorPicker);
7093
frame_popup_item_tint_color_editor->add_child(frame_tint_color_picker);
7094
frame_tint_color_picker->reset_size();
7095
frame_tint_color_picker->connect("color_changed", callable_mp(this, &VisualShaderEditor::_frame_color_changed));
7096
Button *frame_tint_color_confirm_button = memnew(Button);
7097
frame_tint_color_confirm_button->set_text(TTR("OK"));
7098
frame_popup_item_tint_color_editor->add_child(frame_tint_color_confirm_button);
7099
frame_tint_color_confirm_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_frame_color_confirm));
7100
7101
frame_tint_color_pick_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_frame_color_popup_hide));
7102
add_child(frame_tint_color_pick_popup);
7103
7104
///////////////////////////////////////
7105
// SHADER NODES TREE OPTIONS
7106
///////////////////////////////////////
7107
7108
// COLOR
7109
7110
add_options.push_back(AddOption("ColorFunc", "Color/Common", "VisualShaderNodeColorFunc", TTR("Color function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7111
add_options.push_back(AddOption("ColorOp", "Color/Common", "VisualShaderNodeColorOp", TTR("Color operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7112
7113
add_options.push_back(AddOption("Grayscale", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7114
add_options.push_back(AddOption("HSV2RGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeColorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7115
add_options.push_back(AddOption("LinearToSRGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from linear to sRGB color space."), { VisualShaderNodeColorFunc::FUNC_LINEAR_TO_SRGB }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7116
add_options.push_back(AddOption("RGB2HSV", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeColorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7117
add_options.push_back(AddOption("Sepia", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7118
add_options.push_back(AddOption("SRGBToLinear", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from sRGB to linear color space."), { VisualShaderNodeColorFunc::FUNC_SRGB_TO_LINEAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7119
7120
add_options.push_back(AddOption("Burn", "Color/Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7121
add_options.push_back(AddOption("Darken", "Color/Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), { VisualShaderNodeColorOp::OP_DARKEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7122
add_options.push_back(AddOption("Difference", "Color/Operators", "VisualShaderNodeColorOp", TTR("Difference operator."), { VisualShaderNodeColorOp::OP_DIFFERENCE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7123
add_options.push_back(AddOption("Dodge", "Color/Operators", "VisualShaderNodeColorOp", TTR("Dodge operator."), { VisualShaderNodeColorOp::OP_DODGE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7124
add_options.push_back(AddOption("HardLight", "Color/Operators", "VisualShaderNodeColorOp", TTR("HardLight operator."), { VisualShaderNodeColorOp::OP_HARD_LIGHT }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7125
add_options.push_back(AddOption("Lighten", "Color/Operators", "VisualShaderNodeColorOp", TTR("Lighten operator."), { VisualShaderNodeColorOp::OP_LIGHTEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7126
add_options.push_back(AddOption("Overlay", "Color/Operators", "VisualShaderNodeColorOp", TTR("Overlay operator."), { VisualShaderNodeColorOp::OP_OVERLAY }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7127
add_options.push_back(AddOption("Screen", "Color/Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), { VisualShaderNodeColorOp::OP_SCREEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7128
add_options.push_back(AddOption("SoftLight", "Color/Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), { VisualShaderNodeColorOp::OP_SOFT_LIGHT }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7129
7130
add_options.push_back(AddOption("ColorConstant", "Color/Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7131
add_options.push_back(AddOption("ColorParameter", "Color/Variables", "VisualShaderNodeColorParameter", TTR("Color parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7132
7133
// COMMON
7134
7135
add_options.push_back(AddOption("DerivativeFunc", "Common", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) Derivative function."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7136
add_options.push_back(AddOption("DerivativeFunc", "Common", "VisualShaderNodeDerivativeFunc", TTR("Derivative function."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7137
7138
// CONDITIONAL
7139
7140
const String &compare_func_desc = TTR("Returns the boolean result of the %s comparison between two parameters.");
7141
7142
add_options.push_back(AddOption("Equal (==)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Equal (==)")), { VisualShaderNodeCompare::FUNC_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7143
add_options.push_back(AddOption("GreaterThan (>)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Greater Than (>)")), { VisualShaderNodeCompare::FUNC_GREATER_THAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7144
add_options.push_back(AddOption("GreaterThanEqual (>=)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Greater Than or Equal (>=)")), { VisualShaderNodeCompare::FUNC_GREATER_THAN_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7145
add_options.push_back(AddOption("If", "Conditional/Functions", "VisualShaderNodeIf", TTR("Returns an associated vector if the provided scalars are equal, greater or less."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7146
add_options.push_back(AddOption("IsInf", "Conditional/Functions", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between INF and a scalar parameter."), { VisualShaderNodeIs::FUNC_IS_INF }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7147
add_options.push_back(AddOption("IsNaN", "Conditional/Functions", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between NaN and a scalar parameter."), { VisualShaderNodeIs::FUNC_IS_NAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7148
add_options.push_back(AddOption("LessThan (<)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than (<)")), { VisualShaderNodeCompare::FUNC_LESS_THAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7149
add_options.push_back(AddOption("LessThanEqual (<=)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than or Equal (<=)")), { VisualShaderNodeCompare::FUNC_LESS_THAN_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7150
add_options.push_back(AddOption("NotEqual (!=)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Not Equal (!=)")), { VisualShaderNodeCompare::FUNC_NOT_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7151
add_options.push_back(AddOption("SwitchVector2D (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated 2D vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7152
add_options.push_back(AddOption("SwitchVector3D (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated 3D vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7153
add_options.push_back(AddOption("SwitchVector4D (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated 4D vector if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7154
add_options.push_back(AddOption("SwitchBool (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated boolean if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_BOOLEAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7155
add_options.push_back(AddOption("SwitchFloat (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated floating-point scalar if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_FLOAT }, VisualShaderNode::PORT_TYPE_SCALAR));
7156
add_options.push_back(AddOption("SwitchInt (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated integer scalar if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_INT }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7157
add_options.push_back(AddOption("SwitchTransform (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated transform if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_TRANSFORM }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7158
add_options.push_back(AddOption("SwitchUInt (==)", "Conditional/Functions", "VisualShaderNodeSwitch", TTR("Returns an associated unsigned integer scalar if the provided boolean value is true or false."), { VisualShaderNodeSwitch::OP_TYPE_UINT }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7159
7160
add_options.push_back(AddOption("Compare (==)", "Conditional/Common", "VisualShaderNodeCompare", TTR("Returns the boolean result of the comparison between two parameters."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7161
add_options.push_back(AddOption("Is", "Conditional/Common", "VisualShaderNodeIs", TTR("Returns the boolean result of the comparison between INF (or NaN) and a scalar parameter."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7162
7163
add_options.push_back(AddOption("BooleanConstant", "Conditional/Variables", "VisualShaderNodeBooleanConstant", TTR("Boolean constant."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7164
add_options.push_back(AddOption("BooleanParameter", "Conditional/Variables", "VisualShaderNodeBooleanParameter", TTR("Boolean parameter."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7165
7166
// INPUT
7167
7168
const String translation_gdsl = "\n\n" + TTR("Translated to '%s' in Godot Shading Language.");
7169
const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes.") + translation_gdsl;
7170
7171
// NODE3D-FOR-ALL
7172
7173
add_options.push_back(AddOption("ClipSpaceFar", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "clip_space_far", "CLIP_SPACE_FAR"), { "clip_space_far" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
7174
add_options.push_back(AddOption("Exposure", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "exposure", "EXPOSURE"), { "exposure" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
7175
add_options.push_back(AddOption("InShadowPass", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "in_shadow_pass", "IN_SHADOW_PASS"), { "in_shadow_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_SPATIAL));
7176
add_options.push_back(AddOption("InvProjectionMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_projection_matrix", "INV_PROJECTION_MATRIX"), { "inv_projection_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
7177
add_options.push_back(AddOption("InvViewMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_view_matrix", "INV_VIEW_MATRIX"), { "inv_view_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
7178
add_options.push_back(AddOption("ModelMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "model_matrix", "MODEL_MATRIX"), { "model_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
7179
add_options.push_back(AddOption("Normal", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "normal", "NORMAL"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_SPATIAL));
7180
add_options.push_back(AddOption("OutputIsSRGB", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "output_is_srgb", "OUTPUT_IS_SRGB"), { "output_is_srgb" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_SPATIAL));
7181
add_options.push_back(AddOption("ProjectionMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "projection_matrix", "PROJECTION_MATRIX"), { "projection_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
7182
add_options.push_back(AddOption("Time", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_SPATIAL));
7183
add_options.push_back(AddOption("UV", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL));
7184
add_options.push_back(AddOption("UV2", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv2", "UV2"), { "uv2" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL));
7185
add_options.push_back(AddOption("ViewMatrix", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "view_matrix", "VIEW_MATRIX"), { "view_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL));
7186
add_options.push_back(AddOption("ViewportSize", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "viewport_size", "VIEWPORT_SIZE"), { "viewport_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_SPATIAL));
7187
7188
// CANVASITEM-FOR-ALL
7189
7190
add_options.push_back(AddOption("Color", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_CANVAS_ITEM));
7191
add_options.push_back(AddOption("TexturePixelSize", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size", "TEXTURE_PIXEL_SIZE"), { "texture_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM));
7192
add_options.push_back(AddOption("Time", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
7193
add_options.push_back(AddOption("UV", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM));
7194
7195
// PARTICLES-FOR-ALL
7196
7197
add_options.push_back(AddOption("Active", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active", "ACTIVE"), { "active" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES));
7198
add_options.push_back(AddOption("AttractorForce", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "attractor_force", "ATTRACTOR_FORCE"), { "attractor_force" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES));
7199
add_options.push_back(AddOption("Color", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES));
7200
add_options.push_back(AddOption("Custom", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom", "CUSTOM"), { "custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES));
7201
add_options.push_back(AddOption("Delta", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta", "DELTA"), { "delta" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
7202
add_options.push_back(AddOption("EmissionTransform", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform", "EMISSION_TRANSFORM"), { "emission_transform" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES));
7203
add_options.push_back(AddOption("Index", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index", "INDEX"), { "index" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, -1, Shader::MODE_PARTICLES));
7204
add_options.push_back(AddOption("LifeTime", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime", "LIFETIME"), { "lifetime" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
7205
add_options.push_back(AddOption("Number", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "number", "NUMBER"), { "number" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, -1, Shader::MODE_PARTICLES));
7206
add_options.push_back(AddOption("RandomSeed", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "random_seed", "RANDOM_SEED"), { "random_seed" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, -1, Shader::MODE_PARTICLES));
7207
add_options.push_back(AddOption("Restart", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart", "RESTART"), { "restart" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES));
7208
add_options.push_back(AddOption("Time", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
7209
add_options.push_back(AddOption("Transform", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform", "TRANSFORM"), { "transform" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES));
7210
add_options.push_back(AddOption("Velocity", "Input/All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity", "VELOCITY"), { "velocity" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES));
7211
7212
/////////////////
7213
7214
add_options.push_back(AddOption("Input", "Input/Common", "VisualShaderNodeInput", TTR("Input parameter.")));
7215
7216
const String input_param_for_vertex_and_fragment_shader_modes = TTR("'%s' input parameter for vertex and fragment shader modes.") + translation_gdsl;
7217
const String input_param_for_fragment_and_light_shader_modes = TTR("'%s' input parameter for fragment and light shader modes.") + translation_gdsl;
7218
const String input_param_for_fragment_shader_mode = TTR("'%s' input parameter for fragment shader mode.") + translation_gdsl;
7219
const String input_param_for_sky_shader_mode = TTR("'%s' input parameter for sky shader mode.") + translation_gdsl;
7220
const String input_param_for_fog_shader_mode = TTR("'%s' input parameter for fog shader mode.") + translation_gdsl;
7221
const String input_param_for_texture_blit_shader_mode = TTR("'%s' input parameter for blit shader mode.") + translation_gdsl;
7222
const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode.") + translation_gdsl;
7223
const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode.") + translation_gdsl;
7224
const String input_param_for_start_shader_mode = TTR("'%s' input parameter for start shader mode.") + translation_gdsl;
7225
const String input_param_for_process_shader_mode = TTR("'%s' input parameter for process shader mode.") + translation_gdsl;
7226
const String input_param_for_collide_shader_mode = TTR("'%s' input parameter for collide shader mode." + translation_gdsl);
7227
const String input_param_for_start_and_process_shader_mode = TTR("'%s' input parameter for start and process shader modes.") + translation_gdsl;
7228
const String input_param_for_process_and_collide_shader_mode = TTR("'%s' input parameter for process and collide shader modes.") + translation_gdsl;
7229
const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader modes.") + translation_gdsl;
7230
7231
// NODE3D INPUTS
7232
7233
add_options.push_back(AddOption("Binormal", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7234
add_options.push_back(AddOption("CameraDirectionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7235
add_options.push_back(AddOption("CameraPositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7236
add_options.push_back(AddOption("CameraVisibleLayers", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7237
add_options.push_back(AddOption("Color", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7238
add_options.push_back(AddOption("Custom0", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom0", "CUSTOM0"), { "custom0" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7239
add_options.push_back(AddOption("Custom1", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom1", "CUSTOM1"), { "custom1" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7240
add_options.push_back(AddOption("Custom2", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom2", "CUSTOM2"), { "custom2" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7241
add_options.push_back(AddOption("Custom3", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom3", "CUSTOM3"), { "custom3" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7242
add_options.push_back(AddOption("EyeOffset", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7243
add_options.push_back(AddOption("InstanceCustom", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7244
add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7245
add_options.push_back(AddOption("ModelViewMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview_matrix", "MODELVIEW_MATRIX"), { "modelview_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7246
add_options.push_back(AddOption("NodePositionView", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7247
add_options.push_back(AddOption("NodePositionWorld", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7248
add_options.push_back(AddOption("PointSize", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7249
add_options.push_back(AddOption("Tangent", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7250
add_options.push_back(AddOption("Vertex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7251
add_options.push_back(AddOption("VertexId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id", "VERTEX_ID"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7252
add_options.push_back(AddOption("ViewIndex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7253
add_options.push_back(AddOption("ViewMonoLeft", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7254
add_options.push_back(AddOption("ViewRight", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7255
7256
add_options.push_back(AddOption("Binormal", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7257
add_options.push_back(AddOption("CameraDirectionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_direction_world", "CAMERA_DIRECTION_WORLD"), { "camera_direction_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7258
add_options.push_back(AddOption("CameraPositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_position_world", "CAMERA_POSITION_WORLD"), { "camera_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7259
add_options.push_back(AddOption("CameraVisibleLayers", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS"), { "camera_visible_layers" }, VisualShaderNode::PORT_TYPE_SCALAR_UINT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7260
add_options.push_back(AddOption("Color", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7261
add_options.push_back(AddOption("EyeOffset", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "eye_offset", "EYE_OFFSET"), { "eye_offset" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7262
add_options.push_back(AddOption("FragCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7263
add_options.push_back(AddOption("FrontFacing", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing", "FRONT_FACING"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7264
add_options.push_back(AddOption("NodePositionView", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_view", "NODE_POSITION_VIEW"), { "node_position_view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7265
add_options.push_back(AddOption("NodePositionWorld", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "node_position_world", "NODE_POSITION_WORLD"), { "node_position_world" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7266
add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7267
add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7268
add_options.push_back(AddOption("Tangent", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7269
add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7270
add_options.push_back(AddOption("View", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7271
add_options.push_back(AddOption("ViewIndex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index", "VIEW_INDEX"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7272
add_options.push_back(AddOption("ViewMonoLeft", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7273
add_options.push_back(AddOption("ViewRight", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7274
7275
add_options.push_back(AddOption("Albedo", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo", "ALBEDO"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7276
add_options.push_back(AddOption("Attenuation", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7277
add_options.push_back(AddOption("Backlight", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "backlight", "BACKLIGHT"), { "backlight" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7278
add_options.push_back(AddOption("Diffuse", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse", "DIFFUSE_LIGHT"), { "diffuse" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7279
add_options.push_back(AddOption("FragCoord", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7280
add_options.push_back(AddOption("Light", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7281
add_options.push_back(AddOption("LightColor", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7282
add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7283
add_options.push_back(AddOption("Metallic", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic", "METALLIC"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7284
add_options.push_back(AddOption("Roughness", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness", "ROUGHNESS"), { "roughness" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7285
add_options.push_back(AddOption("ScreenUV", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7286
add_options.push_back(AddOption("Specular", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular", "SPECULAR_LIGHT"), { "specular" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7287
add_options.push_back(AddOption("SpecularAmount", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular_amount", "SPECULAR_AMOUNT"), { "specular_amount" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7288
add_options.push_back(AddOption("View", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view", "VIEW"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7289
7290
// CANVASITEM INPUTS
7291
7292
add_options.push_back(AddOption("AtLightPass", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7293
add_options.push_back(AddOption("CanvasMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas_matrix", "CANVAS_MATRIX"), { "canvas_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7294
add_options.push_back(AddOption("Custom0", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom0", "CUSTOM0"), { "custom0" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7295
add_options.push_back(AddOption("Custom1", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom1", "CUSTOM1"), { "custom1" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7296
add_options.push_back(AddOption("InstanceCustom", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7297
add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7298
add_options.push_back(AddOption("ModelMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "model_matrix", "MODEL_MATRIX"), { "model_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7299
add_options.push_back(AddOption("PointSize", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7300
add_options.push_back(AddOption("ScreenMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "screen_matrix", "SCREEN_MATRIX"), { "screen_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7301
add_options.push_back(AddOption("Vertex", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7302
add_options.push_back(AddOption("VertexId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id", "VERTEX_ID"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
7303
7304
add_options.push_back(AddOption("AtLightPass", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7305
add_options.push_back(AddOption("FragCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7306
add_options.push_back(AddOption("NormalTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture", "NORMAL_TEXTURE"), { "normal_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7307
add_options.push_back(AddOption("PointCoord", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7308
add_options.push_back(AddOption("RegionRect", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "region_rect", "REGION_RECT"), { "region_rect" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7309
add_options.push_back(AddOption("ScreenPixelSize", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size", "SCREEN_PIXEL_SIZE"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7310
add_options.push_back(AddOption("ScreenUV", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7311
add_options.push_back(AddOption("SpecularShininess", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7312
add_options.push_back(AddOption("SpecularShininessTexture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE"), { "specular_shininess_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7313
add_options.push_back(AddOption("Texture", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7314
add_options.push_back(AddOption("Vertex", "Input/Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7315
7316
add_options.push_back(AddOption("FragCoord", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7317
add_options.push_back(AddOption("Light", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7318
add_options.push_back(AddOption("LightColor", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7319
add_options.push_back(AddOption("LightDirection", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_direction", "LIGHT_DIRECTION"), { "light_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7320
add_options.push_back(AddOption("LightEnergy", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_energy", "LIGHT_ENERGY"), { "light_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7321
add_options.push_back(AddOption("LightIsDirectional", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_is_directional", "LIGHT_IS_DIRECTIONAL"), { "light_is_directional" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7322
add_options.push_back(AddOption("LightPosition", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position", "LIGHT_POSITION"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7323
add_options.push_back(AddOption("LightVertex", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "light_vertex", "LIGHT_VERTEX"), { "light_vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7324
add_options.push_back(AddOption("Normal", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal", "NORMAL"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7325
add_options.push_back(AddOption("PointCoord", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7326
add_options.push_back(AddOption("ScreenUV", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7327
add_options.push_back(AddOption("Shadow", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow", "SHADOW_MODULATE"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7328
add_options.push_back(AddOption("SpecularShininess", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7329
add_options.push_back(AddOption("Texture", "Input/Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7330
7331
// SKY INPUTS
7332
7333
add_options.push_back(AddOption("AtCubeMapPass", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_cubemap_pass", "AT_CUBEMAP_PASS"), { "at_cubemap_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7334
add_options.push_back(AddOption("AtHalfResPass", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_half_res_pass", "AT_HALF_RES_PASS"), { "at_half_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7335
add_options.push_back(AddOption("AtQuarterResPass", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_quarter_res_pass", "AT_QUARTER_RES_PASS"), { "at_quarter_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7336
add_options.push_back(AddOption("EyeDir", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "eyedir", "EYEDIR"), { "eyedir" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7337
add_options.push_back(AddOption("FragCoord", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7338
add_options.push_back(AddOption("HalfResColor", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7339
add_options.push_back(AddOption("Light0Color", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_color", "LIGHT0_COLOR"), { "light0_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7340
add_options.push_back(AddOption("Light0Direction", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_direction", "LIGHT0_DIRECTION"), { "light0_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7341
add_options.push_back(AddOption("Light0Enabled", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_enabled", "LIGHT0_ENABLED"), { "light0_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7342
add_options.push_back(AddOption("Light0Energy", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_energy", "LIGHT0_ENERGY"), { "light0_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7343
add_options.push_back(AddOption("Light1Color", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light1_color", "LIGHT1_COLOR"), { "light1_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7344
add_options.push_back(AddOption("Light1Direction", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light1_direction", "LIGHT1_DIRECTION"), { "light1_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7345
add_options.push_back(AddOption("Light1Enabled", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light1_enabled", "LIGHT1_ENABLED"), { "light1_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7346
add_options.push_back(AddOption("Light1Energy", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light1_energy", "LIGHT1_ENERGY"), { "light1_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7347
add_options.push_back(AddOption("Light2Color", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light2_color", "LIGHT2_COLOR"), { "light2_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7348
add_options.push_back(AddOption("Light2Direction", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light2_direction", "LIGHT2_DIRECTION"), { "light2_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7349
add_options.push_back(AddOption("Light2Enabled", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light2_enabled", "LIGHT2_ENABLED"), { "light2_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7350
add_options.push_back(AddOption("Light2Energy", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light2_energy", "LIGHT2_ENERGY"), { "light2_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7351
add_options.push_back(AddOption("Light3Color", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_color", "LIGHT3_COLOR"), { "light3_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7352
add_options.push_back(AddOption("Light3Direction", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_direction", "LIGHT3_DIRECTION"), { "light3_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7353
add_options.push_back(AddOption("Light3Enabled", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_enabled", "LIGHT3_ENABLED"), { "light3_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7354
add_options.push_back(AddOption("Light3Energy", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_energy", "LIGHT3_ENERGY"), { "light3_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7355
add_options.push_back(AddOption("Position", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "position", "POSITION"), { "position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7356
add_options.push_back(AddOption("QuarterResColor", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7357
add_options.push_back(AddOption("Radiance", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "radiance", "RADIANCE"), { "radiance" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7358
add_options.push_back(AddOption("ScreenUV", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7359
add_options.push_back(AddOption("SkyCoords", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords", "SKY_COORDS"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7360
add_options.push_back(AddOption("Time", "Input/Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
7361
7362
// FOG INPUTS
7363
7364
add_options.push_back(AddOption("ObjectPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "object_position", "OBJECT_POSITION"), { "object_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7365
add_options.push_back(AddOption("SDF", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "sdf", "SDF"), { "sdf" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7366
add_options.push_back(AddOption("Size", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "size", "SIZE"), { "size" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7367
add_options.push_back(AddOption("Time", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7368
add_options.push_back(AddOption("UVW", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw", "UVW"), { "uvw" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7369
add_options.push_back(AddOption("WorldPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "world_position", "WORLD_POSITION"), { "world_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
7370
7371
// TEXTURE BLIT INPUTS
7372
add_options.push_back(AddOption("UV", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7373
add_options.push_back(AddOption("Modulate", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Modulate", "MODULATE"), { "Modulate" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7374
add_options.push_back(AddOption("Fragcoord", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Fragcoord", "FRAGCOORD"), { "Fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7375
add_options.push_back(AddOption("Source Texture", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture", "source_texture"), { "Source Texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7376
add_options.push_back(AddOption("Source Texture 2", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 2", "source_texture2"), { "Source Texture 2" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7377
add_options.push_back(AddOption("Source Texture 3", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 3", "source_texture3"), { "Source Texture 3" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7378
add_options.push_back(AddOption("Source Texture 4", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 4", "source_texture4"), { "Source Texture 4" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
7379
7380
// PARTICLES INPUTS
7381
7382
add_options.push_back(AddOption("CollisionDepth", "Input/Collide", "VisualShaderNodeInput", vformat(input_param_for_collide_shader_mode, "collision_depth", "COLLISION_DEPTH"), { "collision_depth" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7383
add_options.push_back(AddOption("CollisionNormal", "Input/Collide", "VisualShaderNodeInput", vformat(input_param_for_collide_shader_mode, "collision_normal", "COLLISION_NORMAL"), { "collision_normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7384
7385
// PARTICLES
7386
7387
add_options.push_back(AddOption("EmitParticle", "Particles", "VisualShaderNodeParticleEmit", "", {}, -1, TYPE_FLAGS_PROCESS | TYPE_FLAGS_PROCESS_CUSTOM | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7388
add_options.push_back(AddOption("ParticleAccelerator", "Particles", "VisualShaderNodeParticleAccelerator", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
7389
add_options.push_back(AddOption("ParticleRandomness", "Particles", "VisualShaderNodeParticleRandomness", "", {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7390
add_options.push_back(AddOption("MultiplyByAxisAngle (*)", "Particles/Transform", "VisualShaderNodeParticleMultiplyByAxisAngle", TTR("A node for help to multiply a position input vector by rotation using specific axis. Intended to work with emitters."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7391
7392
add_options.push_back(AddOption("BoxEmitter", "Particles/Emitters", "VisualShaderNodeParticleBoxEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7393
7394
mesh_emitter_option_idx = add_options.size();
7395
add_options.push_back(AddOption("MeshEmitter", "Particles/Emitters", "VisualShaderNodeParticleMeshEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7396
7397
add_options.push_back(AddOption("RingEmitter", "Particles/Emitters", "VisualShaderNodeParticleRingEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7398
add_options.push_back(AddOption("SphereEmitter", "Particles/Emitters", "VisualShaderNodeParticleSphereEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7399
7400
add_options.push_back(AddOption("ConeVelocity", "Particles/Velocity", "VisualShaderNodeParticleConeVelocity", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7401
7402
// SCALAR
7403
7404
add_options.push_back(AddOption("FloatFunc", "Scalar/Common", "VisualShaderNodeFloatFunc", TTR("Float function."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7405
add_options.push_back(AddOption("FloatOp", "Scalar/Common", "VisualShaderNodeFloatOp", TTR("Float operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7406
add_options.push_back(AddOption("IntFunc", "Scalar/Common", "VisualShaderNodeIntFunc", TTR("Integer function."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7407
add_options.push_back(AddOption("IntOp", "Scalar/Common", "VisualShaderNodeIntOp", TTR("Integer operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7408
add_options.push_back(AddOption("UIntFunc", "Scalar/Common", "VisualShaderNodeUIntFunc", TTR("Unsigned integer function."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7409
add_options.push_back(AddOption("UIntOp", "Scalar/Common", "VisualShaderNodeUIntOp", TTR("Unsigned integer operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7410
7411
// CONSTANTS
7412
7413
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
7414
add_options.push_back(AddOption(float_constant_defs[i].name, "Scalar/Constants", "VisualShaderNodeFloatConstant", TTRGET(float_constant_defs[i].desc_key), { float_constant_defs[i].value }, VisualShaderNode::PORT_TYPE_SCALAR));
7415
}
7416
// FUNCTIONS
7417
7418
add_options.push_back(AddOption("Abs", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ABS }, VisualShaderNode::PORT_TYPE_SCALAR));
7419
add_options.push_back(AddOption("Abs", "Scalar/Functions", "VisualShaderNodeIntFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeIntFunc::FUNC_ABS }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7420
add_options.push_back(AddOption("ACos", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ACOS }, VisualShaderNode::PORT_TYPE_SCALAR));
7421
add_options.push_back(AddOption("ACosH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ACOSH }, VisualShaderNode::PORT_TYPE_SCALAR));
7422
add_options.push_back(AddOption("ASin", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ASIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7423
add_options.push_back(AddOption("ASinH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ASINH }, VisualShaderNode::PORT_TYPE_SCALAR));
7424
add_options.push_back(AddOption("ATan", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ATAN }, VisualShaderNode::PORT_TYPE_SCALAR));
7425
add_options.push_back(AddOption("ATan2", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeFloatOp::OP_ATAN2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7426
add_options.push_back(AddOption("ATanH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ATANH }, VisualShaderNode::PORT_TYPE_SCALAR));
7427
add_options.push_back(AddOption("BitwiseNOT", "Scalar/Functions", "VisualShaderNodeIntFunc", TTR("Returns the result of bitwise NOT (~a) operation on the integer."), { VisualShaderNodeIntFunc::FUNC_BITWISE_NOT }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7428
add_options.push_back(AddOption("BitwiseNOT", "Scalar/Functions", "VisualShaderNodeUIntFunc", TTR("Returns the result of bitwise NOT (~a) operation on the unsigned integer."), { VisualShaderNodeUIntFunc::FUNC_BITWISE_NOT }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7429
add_options.push_back(AddOption("Ceil", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeFloatFunc::FUNC_CEIL }, VisualShaderNode::PORT_TYPE_SCALAR));
7430
add_options.push_back(AddOption("Clamp", "Scalar/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_FLOAT }, VisualShaderNode::PORT_TYPE_SCALAR));
7431
add_options.push_back(AddOption("Clamp", "Scalar/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_INT }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7432
add_options.push_back(AddOption("Clamp", "Scalar/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_UINT }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7433
add_options.push_back(AddOption("Cos", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_COS }, VisualShaderNode::PORT_TYPE_SCALAR));
7434
add_options.push_back(AddOption("CosH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_COSH }, VisualShaderNode::PORT_TYPE_SCALAR));
7435
add_options.push_back(AddOption("Degrees", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeFloatFunc::FUNC_DEGREES }, VisualShaderNode::PORT_TYPE_SCALAR));
7436
add_options.push_back(AddOption("DFdX", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7437
add_options.push_back(AddOption("DFdY", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7438
add_options.push_back(AddOption("DFdX", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Scalar) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7439
add_options.push_back(AddOption("DFdY", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Scalar) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7440
add_options.push_back(AddOption("Exp", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-e Exponential."), { VisualShaderNodeFloatFunc::FUNC_EXP }, VisualShaderNode::PORT_TYPE_SCALAR));
7441
add_options.push_back(AddOption("Exp2", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-2 Exponential."), { VisualShaderNodeFloatFunc::FUNC_EXP2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7442
add_options.push_back(AddOption("Floor", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeFloatFunc::FUNC_FLOOR }, VisualShaderNode::PORT_TYPE_SCALAR));
7443
add_options.push_back(AddOption("Fract", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeFloatFunc::FUNC_FRACT }, VisualShaderNode::PORT_TYPE_SCALAR));
7444
add_options.push_back(AddOption("InverseSqrt", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeFloatFunc::FUNC_INVERSE_SQRT }, VisualShaderNode::PORT_TYPE_SCALAR));
7445
add_options.push_back(AddOption("Log", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Natural logarithm."), { VisualShaderNodeFloatFunc::FUNC_LOG }, VisualShaderNode::PORT_TYPE_SCALAR));
7446
add_options.push_back(AddOption("Log2", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-2 logarithm."), { VisualShaderNodeFloatFunc::FUNC_LOG2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7447
add_options.push_back(AddOption("Max", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the greater of two values."), { VisualShaderNodeFloatOp::OP_MAX }, VisualShaderNode::PORT_TYPE_SCALAR));
7448
add_options.push_back(AddOption("Min", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the lesser of two values."), { VisualShaderNodeFloatOp::OP_MIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7449
add_options.push_back(AddOption("Mix", "Scalar/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two scalars."), { VisualShaderNodeMix::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7450
add_options.push_back(AddOption("MultiplyAdd (a * b + c)", "Scalar/Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on scalars."), { VisualShaderNodeMultiplyAdd::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7451
add_options.push_back(AddOption("Negate (*-1)", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeFloatFunc::FUNC_NEGATE }, VisualShaderNode::PORT_TYPE_SCALAR));
7452
add_options.push_back(AddOption("Negate (*-1)", "Scalar/Functions", "VisualShaderNodeIntFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeIntFunc::FUNC_NEGATE }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7453
add_options.push_back(AddOption("Negate (*-1)", "Scalar/Functions", "VisualShaderNodeUIntFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeUIntFunc::FUNC_NEGATE }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7454
add_options.push_back(AddOption("OneMinus (1-)", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("1.0 - scalar"), { VisualShaderNodeFloatFunc::FUNC_ONEMINUS }, VisualShaderNode::PORT_TYPE_SCALAR));
7455
add_options.push_back(AddOption("Pow", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeFloatOp::OP_POW }, VisualShaderNode::PORT_TYPE_SCALAR));
7456
add_options.push_back(AddOption("Radians", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeFloatFunc::FUNC_RADIANS }, VisualShaderNode::PORT_TYPE_SCALAR));
7457
add_options.push_back(AddOption("Reciprocal", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("1.0 / scalar"), { VisualShaderNodeFloatFunc::FUNC_RECIPROCAL }, VisualShaderNode::PORT_TYPE_SCALAR));
7458
add_options.push_back(AddOption("Remap", "Scalar/Functions", "VisualShaderNodeRemap", TTR("Remaps a value from the input range to the output range."), { VisualShaderNodeRemap::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7459
add_options.push_back(AddOption("Round", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeFloatFunc::FUNC_ROUND }, VisualShaderNode::PORT_TYPE_SCALAR));
7460
add_options.push_back(AddOption("RoundEven", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeFloatFunc::FUNC_ROUNDEVEN }, VisualShaderNode::PORT_TYPE_SCALAR));
7461
add_options.push_back(AddOption("Saturate", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeFloatFunc::FUNC_SATURATE }, VisualShaderNode::PORT_TYPE_SCALAR));
7462
add_options.push_back(AddOption("Sign", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SIGN }, VisualShaderNode::PORT_TYPE_SCALAR));
7463
add_options.push_back(AddOption("Sign", "Scalar/Functions", "VisualShaderNodeIntFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeIntFunc::FUNC_SIGN }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7464
add_options.push_back(AddOption("Sin", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7465
add_options.push_back(AddOption("SinH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SINH }, VisualShaderNode::PORT_TYPE_SCALAR));
7466
add_options.push_back(AddOption("Sqrt", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SQRT }, VisualShaderNode::PORT_TYPE_SCALAR));
7467
add_options.push_back(AddOption("SmoothStep", "Scalar/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if x is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7468
add_options.push_back(AddOption("Step", "Scalar/Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), scalar(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7469
add_options.push_back(AddOption("Sum", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7470
add_options.push_back(AddOption("Sum", "Scalar/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Scalar) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7471
add_options.push_back(AddOption("Tan", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TAN }, VisualShaderNode::PORT_TYPE_SCALAR));
7472
add_options.push_back(AddOption("TanH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TANH }, VisualShaderNode::PORT_TYPE_SCALAR));
7473
add_options.push_back(AddOption("Trunc", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TRUNC }, VisualShaderNode::PORT_TYPE_SCALAR));
7474
7475
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Sums two floating-point scalars."), { VisualShaderNodeFloatOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR));
7476
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Sums two integer scalars."), { VisualShaderNodeIntOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7477
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Sums two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7478
add_options.push_back(AddOption("BitwiseAND (&)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the result of bitwise AND (a & b) operation for two integers."), { VisualShaderNodeIntOp::OP_BITWISE_AND }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7479
add_options.push_back(AddOption("BitwiseAND (&)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the result of bitwise AND (a & b) operation for two unsigned integers."), { VisualShaderNodeUIntOp::OP_BITWISE_AND }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7480
add_options.push_back(AddOption("BitwiseLeftShift (<<)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the result of bitwise left shift (a << b) operation on the integer."), { VisualShaderNodeIntOp::OP_BITWISE_LEFT_SHIFT }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7481
add_options.push_back(AddOption("BitwiseLeftShift (<<)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the result of bitwise left shift (a << b) operation on the unsigned integer."), { VisualShaderNodeUIntOp::OP_BITWISE_LEFT_SHIFT }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7482
add_options.push_back(AddOption("BitwiseOR (|)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the result of bitwise OR (a | b) operation for two integers."), { VisualShaderNodeIntOp::OP_BITWISE_OR }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7483
add_options.push_back(AddOption("BitwiseOR (|)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the result of bitwise OR (a | b) operation for two unsigned integers."), { VisualShaderNodeUIntOp::OP_BITWISE_OR }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7484
add_options.push_back(AddOption("BitwiseRightShift (>>)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the result of bitwise right shift (a >> b) operation on the integer."), { VisualShaderNodeIntOp::OP_BITWISE_RIGHT_SHIFT }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7485
add_options.push_back(AddOption("BitwiseRightShift (>>)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the result of bitwise right shift (a >> b) operation on the unsigned integer."), { VisualShaderNodeIntOp::OP_BITWISE_RIGHT_SHIFT }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7486
add_options.push_back(AddOption("BitwiseXOR (^)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the result of bitwise XOR (a ^ b) operation on the integer."), { VisualShaderNodeIntOp::OP_BITWISE_XOR }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7487
add_options.push_back(AddOption("BitwiseXOR (^)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the result of bitwise XOR (a ^ b) operation on the unsigned integer."), { VisualShaderNodeUIntOp::OP_BITWISE_XOR }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7488
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Divides two floating-point scalars."), { VisualShaderNodeFloatOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR));
7489
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Divides two integer scalars."), { VisualShaderNodeIntOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7490
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Divides two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7491
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Multiplies two floating-point scalars."), { VisualShaderNodeFloatOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR));
7492
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Multiplies two integer scalars."), { VisualShaderNodeIntOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7493
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Multiplies two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7494
add_options.push_back(AddOption("Remainder (%)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Returns the remainder of the two floating-point scalars."), { VisualShaderNodeFloatOp::OP_MOD }, VisualShaderNode::PORT_TYPE_SCALAR));
7495
add_options.push_back(AddOption("Remainder (%)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Returns the remainder of the two integer scalars."), { VisualShaderNodeIntOp::OP_MOD }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7496
add_options.push_back(AddOption("Remainder (%)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Returns the remainder of the two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_MOD }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7497
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Subtracts two floating-point scalars."), { VisualShaderNodeFloatOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR));
7498
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Subtracts two integer scalars."), { VisualShaderNodeIntOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7499
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Subtracts two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7500
7501
add_options.push_back(AddOption("FloatConstant", "Scalar/Variables", "VisualShaderNodeFloatConstant", TTR("Scalar floating-point constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7502
add_options.push_back(AddOption("IntConstant", "Scalar/Variables", "VisualShaderNodeIntConstant", TTR("Scalar integer constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7503
add_options.push_back(AddOption("UIntConstant", "Scalar/Variables", "VisualShaderNodeUIntConstant", TTR("Scalar unsigned integer constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7504
add_options.push_back(AddOption("FloatParameter", "Scalar/Variables", "VisualShaderNodeFloatParameter", TTR("Scalar floating-point parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7505
add_options.push_back(AddOption("IntParameter", "Scalar/Variables", "VisualShaderNodeIntParameter", TTR("Scalar integer parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7506
add_options.push_back(AddOption("UIntParameter", "Scalar/Variables", "VisualShaderNodeUIntParameter", TTR("Scalar unsigned integer parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7507
7508
// SDF
7509
{
7510
add_options.push_back(AddOption("ScreenUVToSDF", "SDF", "VisualShaderNodeScreenUVToSDF", TTR("Converts screen UV to a SDF."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7511
add_options.push_back(AddOption("SDFRaymarch", "SDF", "VisualShaderNodeSDFRaymarch", TTR("Casts a ray against the screen SDF and returns the distance travelled."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7512
add_options.push_back(AddOption("SDFToScreenUV", "SDF", "VisualShaderNodeSDFToScreenUV", TTR("Converts a SDF to screen UV."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7513
add_options.push_back(AddOption("TextureSDF", "SDF", "VisualShaderNodeTextureSDF", TTR("Performs a SDF texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7514
add_options.push_back(AddOption("TextureSDFNormal", "SDF", "VisualShaderNodeTextureSDFNormal", TTR("Performs a SDF normal texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7515
}
7516
7517
// TEXTURES
7518
7519
add_options.push_back(AddOption("UVFunc", "Textures/Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7520
add_options.push_back(AddOption("UVPolarCoord", "Textures/Common", "VisualShaderNodeUVPolarCoord", TTR("Polar coordinates conversion applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7521
7522
cubemap_node_option_idx = add_options.size();
7523
add_options.push_back(AddOption("CubeMap", "Textures/Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7524
curve_node_option_idx = add_options.size();
7525
add_options.push_back(AddOption("CurveTexture", "Textures/Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7526
curve_xyz_node_option_idx = add_options.size();
7527
add_options.push_back(AddOption("CurveXYZTexture", "Textures/Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7528
add_options.push_back(AddOption("LinearSceneDepth", "Textures/Functions", "VisualShaderNodeLinearSceneDepth", TTR("Returns the depth value obtained from the depth prepass in a linear space."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7529
texture2d_node_option_idx = add_options.size();
7530
add_options.push_back(AddOption("WorldPositionFromDepth", "Textures/Functions", "VisualShaderNodeWorldPositionFromDepth", TTR("Reconstructs the World Position of the Node from the depth texture."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7531
texture2d_node_option_idx = add_options.size();
7532
add_options.push_back(AddOption("ScreenNormalWorldSpace", "Textures/Functions", "VisualShaderNodeScreenNormalWorldSpace", TTR("Unpacks the Screen Normal Texture in World Space"), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7533
texture2d_node_option_idx = add_options.size();
7534
add_options.push_back(AddOption("Texture2D", "Textures/Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7535
texture2d_array_node_option_idx = add_options.size();
7536
add_options.push_back(AddOption("Texture2DArray", "Textures/Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7537
texture3d_node_option_idx = add_options.size();
7538
add_options.push_back(AddOption("Texture3D", "Textures/Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7539
add_options.push_back(AddOption("UVPanning", "Textures/Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_PANNING }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7540
add_options.push_back(AddOption("UVScaling", "Textures/Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_SCALING }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7541
7542
add_options.push_back(AddOption("CubeMapParameter", "Textures/Variables", "VisualShaderNodeCubemapParameter", TTR("Cubic texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7543
add_options.push_back(AddOption("Texture2DParameter", "Textures/Variables", "VisualShaderNodeTexture2DParameter", TTR("2D texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7544
add_options.push_back(AddOption("TextureParameterTriplanar", "Textures/Variables", "VisualShaderNodeTextureParameterTriplanar", TTR("2D texture parameter lookup with triplanar."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7545
add_options.push_back(AddOption("Texture2DArrayParameter", "Textures/Variables", "VisualShaderNodeTexture2DArrayParameter", TTR("2D array of textures parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7546
add_options.push_back(AddOption("Texture3DParameter", "Textures/Variables", "VisualShaderNodeTexture3DParameter", TTR("3D texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7547
7548
// TRANSFORM
7549
7550
add_options.push_back(AddOption("TransformFunc", "Transform/Common", "VisualShaderNodeTransformFunc", TTR("Transform function."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7551
add_options.push_back(AddOption("TransformOp", "Transform/Common", "VisualShaderNodeTransformOp", TTR("Transform operator."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7552
7553
add_options.push_back(AddOption("OuterProduct", "Transform/Composition", "VisualShaderNodeOuterProduct", TTR("Calculate the outer product of a pair of vectors.\n\nOuterProduct treats the first parameter 'c' as a column vector (matrix with one column) and the second parameter 'r' as a row vector (matrix with one row) and does a linear algebraic matrix multiply 'c * r', yielding a matrix whose number of rows is the number of components in 'c' and whose number of columns is the number of components in 'r'."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7554
add_options.push_back(AddOption("TransformCompose", "Transform/Composition", "VisualShaderNodeTransformCompose", TTR("Composes transform from four vectors."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7555
add_options.push_back(AddOption("TransformDecompose", "Transform/Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors.")));
7556
7557
add_options.push_back(AddOption("Determinant", "Transform/Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7558
add_options.push_back(AddOption("GetBillboardMatrix", "Transform/Functions", "VisualShaderNodeBillboard", TTR("Calculates how the object should face the camera to be applied on Model View Matrix output port for 3D objects."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
7559
add_options.push_back(AddOption("Inverse", "Transform/Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), { VisualShaderNodeTransformFunc::FUNC_INVERSE }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7560
add_options.push_back(AddOption("Transpose", "Transform/Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), { VisualShaderNodeTransformFunc::FUNC_TRANSPOSE }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7561
7562
add_options.push_back(AddOption("Add (+)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Sums two transforms."), { VisualShaderNodeTransformOp::OP_ADD }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7563
add_options.push_back(AddOption("Divide (/)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Divides two transforms."), { VisualShaderNodeTransformOp::OP_A_DIV_B }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7564
add_options.push_back(AddOption("Multiply (*)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Multiplies two transforms."), { VisualShaderNodeTransformOp::OP_AxB }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7565
add_options.push_back(AddOption("MultiplyComp (*)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Performs per-component multiplication of two transforms."), { VisualShaderNodeTransformOp::OP_AxB_COMP }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7566
add_options.push_back(AddOption("Subtract (-)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Subtracts two transforms."), { VisualShaderNodeTransformOp::OP_A_MINUS_B }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7567
add_options.push_back(AddOption("TransformVectorMult (*)", "Transform/Operators", "VisualShaderNodeTransformVecMult", TTR("Multiplies vector by transform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7568
7569
add_options.push_back(AddOption("TransformConstant", "Transform/Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7570
add_options.push_back(AddOption("TransformParameter", "Transform/Variables", "VisualShaderNodeTransformParameter", TTR("Transform parameter."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7571
7572
// UTILITY
7573
7574
add_options.push_back(AddOption("DistanceFade", "Utility", "VisualShaderNodeDistanceFade", TTR("The distance fade effect fades out each pixel based on its distance to another object."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7575
add_options.push_back(AddOption("ProximityFade", "Utility", "VisualShaderNodeProximityFade", TTR("The proximity fade effect fades out each pixel based on its distance to another object."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7576
add_options.push_back(AddOption("RandomRange", "Utility", "VisualShaderNodeRandomRange", TTR("Returns a random value between the minimum and maximum input values."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7577
add_options.push_back(AddOption("RotationByAxis", "Utility", "VisualShaderNodeRotationByAxis", TTR("Builds a rotation matrix from the given axis and angle, multiply the input vector by it and returns both this vector and a matrix."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7578
7579
// VECTOR
7580
7581
add_options.push_back(AddOption("VectorFunc", "Vector/Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7582
add_options.push_back(AddOption("VectorOp", "Vector/Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7583
add_options.push_back(AddOption("VectorCompose", "Vector/Common", "VisualShaderNodeVectorCompose", TTR("Composes vector from scalars.")));
7584
add_options.push_back(AddOption("VectorDecompose", "Vector/Common", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to scalars.")));
7585
7586
add_options.push_back(AddOption("Vector2Compose", "Vector/Composition", "VisualShaderNodeVectorCompose", TTR("Composes 2D vector from two scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7587
add_options.push_back(AddOption("Vector2Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 2D vector to two scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_2D }));
7588
add_options.push_back(AddOption("Vector3Compose", "Vector/Composition", "VisualShaderNodeVectorCompose", TTR("Composes 3D vector from three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7589
add_options.push_back(AddOption("Vector3Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 3D vector to three scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_3D }));
7590
add_options.push_back(AddOption("Vector4Compose", "Vector/Composition", "VisualShaderNodeVectorCompose", TTR("Composes 4D vector from four scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7591
add_options.push_back(AddOption("Vector4Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 4D vector to four scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_4D }));
7592
7593
add_options.push_back(AddOption("Abs", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7594
add_options.push_back(AddOption("Abs", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7595
add_options.push_back(AddOption("Abs", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7596
add_options.push_back(AddOption("ACos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7597
add_options.push_back(AddOption("ACos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7598
add_options.push_back(AddOption("ACos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7599
add_options.push_back(AddOption("ACosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7600
add_options.push_back(AddOption("ACosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7601
add_options.push_back(AddOption("ACosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7602
add_options.push_back(AddOption("ASin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7603
add_options.push_back(AddOption("ASin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7604
add_options.push_back(AddOption("ASin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7605
add_options.push_back(AddOption("ASinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7606
add_options.push_back(AddOption("ASinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7607
add_options.push_back(AddOption("ASinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7608
add_options.push_back(AddOption("ATan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7609
add_options.push_back(AddOption("ATan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7610
add_options.push_back(AddOption("ATan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7611
add_options.push_back(AddOption("ATan2", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7612
add_options.push_back(AddOption("ATan2", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7613
add_options.push_back(AddOption("ATan2", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7614
add_options.push_back(AddOption("ATanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7615
add_options.push_back(AddOption("ATanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7616
add_options.push_back(AddOption("ATanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7617
add_options.push_back(AddOption("Ceil", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7618
add_options.push_back(AddOption("Ceil", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7619
add_options.push_back(AddOption("Ceil", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7620
add_options.push_back(AddOption("Clamp", "Vector/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7621
add_options.push_back(AddOption("Clamp", "Vector/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7622
add_options.push_back(AddOption("Clamp", "Vector/Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7623
add_options.push_back(AddOption("Cos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7624
add_options.push_back(AddOption("Cos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7625
add_options.push_back(AddOption("Cos", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7626
add_options.push_back(AddOption("CosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7627
add_options.push_back(AddOption("CosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7628
add_options.push_back(AddOption("CosH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7629
add_options.push_back(AddOption("Cross", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), { VisualShaderNodeVectorOp::OP_CROSS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7630
add_options.push_back(AddOption("Degrees", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7631
add_options.push_back(AddOption("Degrees", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7632
add_options.push_back(AddOption("Degrees", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7633
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7634
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7635
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7636
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7637
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7638
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7639
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7640
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7641
add_options.push_back(AddOption("DFdX", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7642
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7643
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7644
add_options.push_back(AddOption("DFdY", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7645
add_options.push_back(AddOption("Distance2D", "Vector/Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR));
7646
add_options.push_back(AddOption("Distance3D", "Vector/Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR));
7647
add_options.push_back(AddOption("Distance4D", "Vector/Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_SCALAR));
7648
add_options.push_back(AddOption("Dot", "Vector/Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7649
add_options.push_back(AddOption("Exp", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7650
add_options.push_back(AddOption("Exp", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7651
add_options.push_back(AddOption("Exp", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7652
add_options.push_back(AddOption("Exp2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7653
add_options.push_back(AddOption("Exp2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7654
add_options.push_back(AddOption("Exp2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7655
add_options.push_back(AddOption("FaceForward", "Vector/Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7656
add_options.push_back(AddOption("FaceForward", "Vector/Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7657
add_options.push_back(AddOption("FaceForward", "Vector/Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7658
add_options.push_back(AddOption("Floor", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7659
add_options.push_back(AddOption("Floor", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7660
add_options.push_back(AddOption("Floor", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7661
add_options.push_back(AddOption("Fract", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRACT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7662
add_options.push_back(AddOption("Fract", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRACT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7663
add_options.push_back(AddOption("Fract", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRACT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7664
add_options.push_back(AddOption("Fresnel", "Vector/Functions", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7665
add_options.push_back(AddOption("InverseSqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7666
add_options.push_back(AddOption("InverseSqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7667
add_options.push_back(AddOption("InverseSqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7668
add_options.push_back(AddOption("Length2D", "Vector/Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR));
7669
add_options.push_back(AddOption("Length3D", "Vector/Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR));
7670
add_options.push_back(AddOption("Length4D", "Vector/Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_SCALAR));
7671
add_options.push_back(AddOption("Log", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7672
add_options.push_back(AddOption("Log", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7673
add_options.push_back(AddOption("Log", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7674
add_options.push_back(AddOption("Log2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7675
add_options.push_back(AddOption("Log2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7676
add_options.push_back(AddOption("Log2", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7677
add_options.push_back(AddOption("Max", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7678
add_options.push_back(AddOption("Max", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7679
add_options.push_back(AddOption("Max", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7680
add_options.push_back(AddOption("Min", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7681
add_options.push_back(AddOption("Min", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7682
add_options.push_back(AddOption("Min", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7683
add_options.push_back(AddOption("Mix", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7684
add_options.push_back(AddOption("Mix", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7685
add_options.push_back(AddOption("Mix", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7686
add_options.push_back(AddOption("MixS", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7687
add_options.push_back(AddOption("MixS", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7688
add_options.push_back(AddOption("MixS", "Vector/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7689
add_options.push_back(AddOption("MultiplyAdd (a * b + c)", "Vector/Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7690
add_options.push_back(AddOption("MultiplyAdd (a * b + c)", "Vector/Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7691
add_options.push_back(AddOption("MultiplyAdd (a * b + c)", "Vector/Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7692
add_options.push_back(AddOption("Negate (*-1)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7693
add_options.push_back(AddOption("Negate (*-1)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7694
add_options.push_back(AddOption("Negate (*-1)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7695
add_options.push_back(AddOption("Normalize", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7696
add_options.push_back(AddOption("Normalize", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7697
add_options.push_back(AddOption("Normalize", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7698
add_options.push_back(AddOption("OneMinus (1-)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7699
add_options.push_back(AddOption("OneMinus (1-)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7700
add_options.push_back(AddOption("OneMinus (1-)", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7701
add_options.push_back(AddOption("Pow (^)", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7702
add_options.push_back(AddOption("Pow (^)", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7703
add_options.push_back(AddOption("Pow (^)", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7704
add_options.push_back(AddOption("Radians", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7705
add_options.push_back(AddOption("Radians", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7706
add_options.push_back(AddOption("Radians", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7707
add_options.push_back(AddOption("Reciprocal", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7708
add_options.push_back(AddOption("Reciprocal", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7709
add_options.push_back(AddOption("Reciprocal", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7710
add_options.push_back(AddOption("Reflect", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7711
add_options.push_back(AddOption("Reflect", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7712
add_options.push_back(AddOption("Reflect", "Vector/Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7713
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), { VisualShaderNodeVectorRefract::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7714
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), { VisualShaderNodeVectorRefract::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7715
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), { VisualShaderNodeVectorRefract::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7716
add_options.push_back(AddOption("Remap", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7717
add_options.push_back(AddOption("Remap", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7718
add_options.push_back(AddOption("Remap", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7719
add_options.push_back(AddOption("RemapS", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range. Ranges defined with scalars."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7720
add_options.push_back(AddOption("RemapS", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range. Ranges defined with scalars."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7721
add_options.push_back(AddOption("RemapS", "Vector/Functions", "VisualShaderNodeRemap", TTR("Remaps a vector from the input range to the output range. Ranges defined with scalars."), { VisualShaderNodeRemap::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7722
add_options.push_back(AddOption("Round", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7723
add_options.push_back(AddOption("Round", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7724
add_options.push_back(AddOption("Round", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7725
add_options.push_back(AddOption("RoundEven", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7726
add_options.push_back(AddOption("RoundEven", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7727
add_options.push_back(AddOption("RoundEven", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7728
add_options.push_back(AddOption("Saturate", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7729
add_options.push_back(AddOption("Saturate", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7730
add_options.push_back(AddOption("Saturate", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7731
add_options.push_back(AddOption("Sign", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7732
add_options.push_back(AddOption("Sign", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7733
add_options.push_back(AddOption("Sign", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7734
add_options.push_back(AddOption("Sin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7735
add_options.push_back(AddOption("Sin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7736
add_options.push_back(AddOption("Sin", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7737
add_options.push_back(AddOption("SinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7738
add_options.push_back(AddOption("SinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7739
add_options.push_back(AddOption("SinH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7740
add_options.push_back(AddOption("Sqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7741
add_options.push_back(AddOption("Sqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7742
add_options.push_back(AddOption("Sqrt", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7743
add_options.push_back(AddOption("SmoothStep", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7744
add_options.push_back(AddOption("SmoothStep", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7745
add_options.push_back(AddOption("SmoothStep", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7746
add_options.push_back(AddOption("SmoothStepS", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7747
add_options.push_back(AddOption("SmoothStepS", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7748
add_options.push_back(AddOption("SmoothStepS", "Vector/Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7749
add_options.push_back(AddOption("Step", "Vector/Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7750
add_options.push_back(AddOption("Step", "Vector/Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7751
add_options.push_back(AddOption("StepS", "Vector/Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7752
add_options.push_back(AddOption("StepS", "Vector/Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7753
add_options.push_back(AddOption("StepS", "Vector/Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7754
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7755
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7756
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
7757
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7758
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7759
add_options.push_back(AddOption("Sum (+)", "Vector/Functions", "VisualShaderNodeDerivativeFunc", TTR("(Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7760
add_options.push_back(AddOption("Tan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7761
add_options.push_back(AddOption("Tan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7762
add_options.push_back(AddOption("Tan", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7763
add_options.push_back(AddOption("TanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7764
add_options.push_back(AddOption("TanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7765
add_options.push_back(AddOption("TanH", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7766
add_options.push_back(AddOption("Trunc", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7767
add_options.push_back(AddOption("Trunc", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7768
add_options.push_back(AddOption("Trunc", "Vector/Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7769
7770
add_options.push_back(AddOption("Add (+)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Adds 2D vector to 2D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7771
add_options.push_back(AddOption("Add (+)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Adds 3D vector to 3D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7772
add_options.push_back(AddOption("Add (+)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Adds 4D vector to 4D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7773
add_options.push_back(AddOption("Divide (/)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Divides 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7774
add_options.push_back(AddOption("Divide (/)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Divides 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7775
add_options.push_back(AddOption("Divide (/)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Divides 4D vector by 4D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7776
add_options.push_back(AddOption("Multiply (*)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7777
add_options.push_back(AddOption("Multiply (*)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7778
add_options.push_back(AddOption("Multiply (*)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 4D vector by 4D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7779
add_options.push_back(AddOption("Remainder (%)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 2D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7780
add_options.push_back(AddOption("Remainder (%)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 3D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7781
add_options.push_back(AddOption("Remainder (%)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 4D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7782
add_options.push_back(AddOption("Subtract (-)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 2D vector from 2D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7783
add_options.push_back(AddOption("Subtract (-)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 3D vector from 3D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7784
add_options.push_back(AddOption("Subtract (-)", "Vector/Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 4D vector from 4D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7785
7786
add_options.push_back(AddOption("Vector2Constant", "Vector/Variables", "VisualShaderNodeVec2Constant", TTR("2D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7787
add_options.push_back(AddOption("Vector2Parameter", "Vector/Variables", "VisualShaderNodeVec2Parameter", TTR("2D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7788
add_options.push_back(AddOption("Vector3Constant", "Vector/Variables", "VisualShaderNodeVec3Constant", TTR("3D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7789
add_options.push_back(AddOption("Vector3Parameter", "Vector/Variables", "VisualShaderNodeVec3Parameter", TTR("3D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7790
add_options.push_back(AddOption("Vector4Constant", "Vector/Variables", "VisualShaderNodeVec4Constant", TTR("4D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7791
add_options.push_back(AddOption("Vector4Parameter", "Vector/Variables", "VisualShaderNodeVec4Parameter", TTR("4D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7792
7793
// SPECIAL
7794
add_options.push_back(AddOption("Frame", "Special", "VisualShaderNodeFrame", TTR("A rectangular area with a description string for better graph organization.")));
7795
add_options.push_back(AddOption("Expression", "Special", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside.")));
7796
add_options.push_back(AddOption("GlobalExpression", "Special", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, parameters and constants.")));
7797
add_options.push_back(AddOption("ParameterRef", "Special", "VisualShaderNodeParameterRef", TTR("A reference to an existing parameter.")));
7798
add_options.push_back(AddOption("VaryingGetter", "Special", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7799
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7800
add_options.push_back(AddOption("VaryingGetter", "Special", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7801
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7802
add_options.push_back(AddOption("Reroute", "Special", "VisualShaderNodeReroute", TTR("Reroute connections freely, can be used to connect multiple input ports to single output port.")));
7803
7804
custom_node_option_idx = add_options.size();
7805
7806
/////////////////////////////////////////////////////////////////////
7807
7808
Ref<VisualShaderNodePluginDefault> default_plugin;
7809
default_plugin.instantiate();
7810
default_plugin->set_editor(this);
7811
add_plugin(default_plugin);
7812
7813
graph_plugin.instantiate();
7814
graph_plugin->set_editor(this);
7815
7816
property_editor_popup = memnew(PopupPanel);
7817
property_editor_popup->set_min_size(Size2(360, 0) * EDSCALE);
7818
add_child(property_editor_popup);
7819
7820
edited_property_holder.instantiate();
7821
7822
panning_debounce_timer = memnew(Timer);
7823
panning_debounce_timer->set_one_shot(true);
7824
panning_debounce_timer->set_wait_time(1.0);
7825
panning_debounce_timer->connect("timeout", callable_mp(this, &VisualShaderEditor::save_editor_layout));
7826
add_child(panning_debounce_timer);
7827
}
7828
7829
VisualShaderEditor::~VisualShaderEditor() {
7830
save_editor_layout();
7831
}
7832
7833
class VisualShaderNodePluginInputEditor : public OptionButton {
7834
GDCLASS(VisualShaderNodePluginInputEditor, OptionButton);
7835
7836
VisualShaderEditor *editor = nullptr;
7837
Ref<VisualShaderNodeInput> input;
7838
7839
public:
7840
void _notification(int p_what) {
7841
switch (p_what) {
7842
case NOTIFICATION_READY: {
7843
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginInputEditor::_item_selected));
7844
} break;
7845
}
7846
}
7847
7848
void _item_selected(int p_item) {
7849
editor->call_deferred(SNAME("_input_select_item"), input, get_item_metadata(p_item));
7850
}
7851
7852
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeInput> &p_input) {
7853
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7854
7855
editor = p_editor;
7856
input = p_input;
7857
7858
Ref<Texture2D> type_icon[] = {
7859
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7860
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
7861
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
7862
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
7863
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
7864
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
7865
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
7866
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
7867
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("ImageTexture"), EditorStringName(EditorIcons)),
7868
};
7869
7870
add_item(TTR("[None]"));
7871
set_item_metadata(-1, "[None]");
7872
7873
int to_select = -1;
7874
for (int i = 0; i < input->get_input_index_count(); i++) {
7875
if (input->get_input_name() == input->get_input_index_name(i)) {
7876
to_select = i + 1;
7877
}
7878
add_icon_item(type_icon[input->get_input_index_type(i)], input->get_input_index_name(i));
7879
set_item_metadata(-1, input->get_input_index_name(i));
7880
}
7881
7882
if (to_select >= 0) {
7883
select(to_select);
7884
}
7885
}
7886
};
7887
7888
////////////////
7889
7890
class VisualShaderNodePluginVaryingEditor : public OptionButton {
7891
GDCLASS(VisualShaderNodePluginVaryingEditor, OptionButton);
7892
7893
VisualShaderEditor *editor = nullptr;
7894
Ref<VisualShaderNodeVarying> varying;
7895
7896
public:
7897
void _notification(int p_what) {
7898
if (p_what == NOTIFICATION_READY) {
7899
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginVaryingEditor::_item_selected));
7900
}
7901
}
7902
7903
void _item_selected(int p_item) {
7904
editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_metadata(p_item));
7905
}
7906
7907
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) {
7908
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7909
7910
editor = p_editor;
7911
varying = p_varying;
7912
7913
Ref<Texture2D> type_icon[] = {
7914
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7915
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
7916
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
7917
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
7918
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
7919
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
7920
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
7921
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
7922
};
7923
7924
bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
7925
7926
add_item(TTR("[None]"));
7927
set_item_metadata(-1, "[None]");
7928
7929
int to_select = -1;
7930
for (int i = 0, j = 0; i < varying->get_varyings_count(); i++) {
7931
VisualShader::VaryingMode mode = varying->get_varying_mode_by_index(i);
7932
if (is_getter) {
7933
if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
7934
if (p_type != VisualShader::TYPE_LIGHT) {
7935
j++;
7936
continue;
7937
}
7938
} else {
7939
if (p_type != VisualShader::TYPE_FRAGMENT && p_type != VisualShader::TYPE_LIGHT) {
7940
j++;
7941
continue;
7942
}
7943
}
7944
} else {
7945
if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
7946
if (p_type != VisualShader::TYPE_FRAGMENT) {
7947
j++;
7948
continue;
7949
}
7950
} else {
7951
if (p_type != VisualShader::TYPE_VERTEX) {
7952
j++;
7953
continue;
7954
}
7955
}
7956
}
7957
if (varying->get_varying_name() == varying->get_varying_name_by_index(i)) {
7958
to_select = i - j + 1;
7959
}
7960
add_icon_item(type_icon[varying->get_varying_type_by_index(i)], varying->get_varying_name_by_index(i));
7961
set_item_metadata(-1, varying->get_varying_name_by_index(i));
7962
}
7963
7964
if (to_select >= 0) {
7965
select(to_select);
7966
}
7967
}
7968
};
7969
7970
////////////////
7971
7972
class VisualShaderNodePluginParameterRefEditor : public OptionButton {
7973
GDCLASS(VisualShaderNodePluginParameterRefEditor, OptionButton);
7974
7975
VisualShaderEditor *editor = nullptr;
7976
Ref<VisualShaderNodeParameterRef> parameter_ref;
7977
7978
public:
7979
void _notification(int p_what) {
7980
switch (p_what) {
7981
case NOTIFICATION_READY: {
7982
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginParameterRefEditor::_item_selected));
7983
} break;
7984
}
7985
}
7986
7987
void _item_selected(int p_item) {
7988
editor->call_deferred(SNAME("_parameter_ref_select_item"), parameter_ref, get_item_metadata(p_item));
7989
}
7990
7991
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeParameterRef> &p_parameter_ref) {
7992
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7993
7994
editor = p_editor;
7995
parameter_ref = p_parameter_ref;
7996
7997
Ref<Texture2D> type_icon[] = {
7998
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7999
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
8000
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
8001
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
8002
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
8003
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
8004
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
8005
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
8006
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Color"), EditorStringName(EditorIcons)),
8007
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("ImageTexture"), EditorStringName(EditorIcons)),
8008
};
8009
8010
add_item(TTR("[None]"));
8011
set_item_metadata(-1, "[None]");
8012
8013
int to_select = -1;
8014
for (int i = 0; i < p_parameter_ref->get_parameters_count(); i++) {
8015
if (p_parameter_ref->get_parameter_name() == p_parameter_ref->get_parameter_name_by_index(i)) {
8016
to_select = i + 1;
8017
}
8018
add_icon_item(type_icon[p_parameter_ref->get_parameter_type_by_index(i)], p_parameter_ref->get_parameter_name_by_index(i));
8019
set_item_metadata(-1, p_parameter_ref->get_parameter_name_by_index(i));
8020
}
8021
8022
if (to_select >= 0) {
8023
select(to_select);
8024
}
8025
}
8026
};
8027
8028
////////////////
8029
8030
class VisualShaderNodePluginDefaultEditor : public VBoxContainer {
8031
GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer);
8032
VisualShaderEditor *editor = nullptr;
8033
Ref<Resource> parent_resource;
8034
int node_id = 0;
8035
VisualShader::Type shader_type;
8036
8037
public:
8038
void _property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false) {
8039
if (p_changing) {
8040
return;
8041
}
8042
8043
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
8044
8045
updating = true;
8046
undo_redo->create_action(vformat(TTR("Edit Visual Property: %s"), p_property), UndoRedo::MERGE_ENDS);
8047
undo_redo->add_do_property(node.ptr(), p_property, p_value);
8048
undo_redo->add_undo_property(node.ptr(), p_property, node->get(p_property));
8049
8050
Ref<VisualShaderNode> vsnode = editor->get_visual_shader()->get_node(shader_type, node_id);
8051
ERR_FAIL_COND(vsnode.is_null());
8052
8053
// Check for invalid connections due to removed ports.
8054
// We need to know the new state of the node to generate the proper undo/redo instructions.
8055
// Quite hacky but the best way I could come up with for now.
8056
Ref<VisualShaderNode> vsnode_new = vsnode->duplicate();
8057
vsnode_new->set(p_property, p_value);
8058
const int input_port_count = vsnode_new->get_input_port_count();
8059
const int output_port_count = vsnode_new->get_expanded_output_port_count();
8060
8061
List<VisualShader::Connection> conns;
8062
editor->get_visual_shader()->get_node_connections(shader_type, &conns);
8063
VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
8064
bool undo_node_already_updated = false;
8065
for (const VisualShader::Connection &c : conns) {
8066
if ((c.from_node == node_id && c.from_port >= output_port_count) || (c.to_node == node_id && c.to_port >= input_port_count)) {
8067
undo_redo->add_do_method(editor->get_visual_shader().ptr(), "disconnect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8068
undo_redo->add_do_method(graph_plugin, "disconnect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8069
// We need to update the node before reconnecting to avoid accessing a non-existing port.
8070
undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8071
undo_node_already_updated = true;
8072
undo_redo->add_undo_method(editor->get_visual_shader().ptr(), "connect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8073
undo_redo->add_undo_method(graph_plugin, "connect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8074
}
8075
}
8076
8077
if (p_value.get_type() == Variant::OBJECT) {
8078
Ref<Resource> prev_res = vsnode->get(p_property);
8079
Ref<Resource> curr_res = p_value;
8080
8081
if (curr_res.is_null()) {
8082
undo_redo->add_do_method(this, "_open_inspector", (Ref<Resource>)parent_resource.ptr());
8083
} else {
8084
undo_redo->add_do_method(this, "_open_inspector", (Ref<Resource>)curr_res.ptr());
8085
}
8086
if (prev_res.is_valid()) {
8087
undo_redo->add_undo_method(this, "_open_inspector", (Ref<Resource>)prev_res.ptr());
8088
} else {
8089
undo_redo->add_undo_method(this, "_open_inspector", (Ref<Resource>)parent_resource.ptr());
8090
}
8091
}
8092
if (p_property != "constant") {
8093
if (graph_plugin) {
8094
undo_redo->add_do_method(editor, "_update_next_previews", node_id);
8095
undo_redo->add_undo_method(editor, "_update_next_previews", node_id);
8096
undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8097
if (!undo_node_already_updated) {
8098
undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8099
}
8100
}
8101
}
8102
8103
undo_redo->commit_action();
8104
8105
updating = false;
8106
}
8107
8108
void _node_changed() {
8109
if (updating) {
8110
return;
8111
}
8112
for (int i = 0; i < properties.size(); i++) {
8113
properties[i]->update_property();
8114
}
8115
}
8116
8117
void _resource_selected(const String &p_path, Ref<Resource> p_resource) {
8118
_open_inspector(p_resource);
8119
}
8120
8121
void _open_inspector(Ref<Resource> p_resource) {
8122
InspectorDock::get_inspector_singleton()->edit(p_resource.ptr());
8123
}
8124
8125
bool updating = false;
8126
Ref<VisualShaderNode> node;
8127
Vector<EditorProperty *> properties;
8128
Vector<Label *> prop_names;
8129
8130
void _show_prop_names(bool p_show) {
8131
for (int i = 0; i < prop_names.size(); i++) {
8132
prop_names[i]->set_visible(p_show);
8133
}
8134
}
8135
8136
void setup(VisualShaderEditor *p_editor, Ref<Resource> p_parent_resource, const Vector<EditorProperty *> &p_properties, const Vector<StringName> &p_names, const HashMap<StringName, String> &p_overrided_names, Ref<VisualShaderNode> p_node) {
8137
editor = p_editor;
8138
parent_resource = p_parent_resource;
8139
updating = false;
8140
node = p_node;
8141
properties = p_properties;
8142
8143
node_id = (int)p_node->get_meta("id");
8144
shader_type = VisualShader::Type((int)p_node->get_meta("shader_type"));
8145
8146
for (int i = 0; i < p_properties.size(); i++) {
8147
HBoxContainer *hbox = memnew(HBoxContainer);
8148
hbox->set_h_size_flags(SIZE_EXPAND_FILL);
8149
add_child(hbox);
8150
8151
Label *prop_name = memnew(Label);
8152
prop_name->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
8153
String prop_name_str = p_names[i];
8154
if (p_overrided_names.has(p_names[i])) {
8155
prop_name_str = p_overrided_names[p_names[i]] + ":";
8156
} else {
8157
prop_name_str = prop_name_str.capitalize() + ":";
8158
}
8159
prop_name->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
8160
prop_name->set_text(prop_name_str);
8161
prop_name->set_visible(false);
8162
hbox->add_child(prop_name);
8163
prop_names.push_back(prop_name);
8164
8165
p_properties[i]->set_h_size_flags(SIZE_EXPAND_FILL);
8166
hbox->add_child(p_properties[i]);
8167
8168
bool res_prop = Object::cast_to<EditorPropertyResource>(p_properties[i]);
8169
if (res_prop) {
8170
p_properties[i]->connect("resource_selected", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_resource_selected));
8171
}
8172
8173
properties[i]->connect("property_changed", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_property_changed));
8174
properties[i]->set_object_and_property(node.ptr(), p_names[i]);
8175
properties[i]->update_property();
8176
properties[i]->set_name_split_ratio(0);
8177
}
8178
node->connect_changed(callable_mp(this, &VisualShaderNodePluginDefaultEditor::_node_changed));
8179
}
8180
8181
static void _bind_methods() {
8182
ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); // Used by UndoRedo.
8183
ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); // Used with call_deferred.
8184
}
8185
};
8186
8187
Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
8188
Ref<VisualShader> p_shader = Ref<VisualShader>(p_parent_resource.ptr());
8189
8190
if (p_shader.is_valid() && (p_node->is_class("VisualShaderNodeVaryingGetter") || p_node->is_class("VisualShaderNodeVaryingSetter"))) {
8191
VisualShaderNodePluginVaryingEditor *editor = memnew(VisualShaderNodePluginVaryingEditor);
8192
editor->setup(vseditor, p_node, vseditor->get_current_shader_type());
8193
return editor;
8194
}
8195
8196
if (p_node->is_class("VisualShaderNodeParameterRef")) {
8197
VisualShaderNodePluginParameterRefEditor *editor = memnew(VisualShaderNodePluginParameterRefEditor);
8198
editor->setup(vseditor, p_node);
8199
return editor;
8200
}
8201
8202
if (p_node->is_class("VisualShaderNodeInput")) {
8203
VisualShaderNodePluginInputEditor *editor = memnew(VisualShaderNodePluginInputEditor);
8204
editor->setup(vseditor, p_node);
8205
return editor;
8206
}
8207
8208
Vector<StringName> properties = p_node->get_editable_properties();
8209
if (properties.is_empty()) {
8210
return nullptr;
8211
}
8212
8213
List<PropertyInfo> props;
8214
p_node->get_property_list(&props);
8215
8216
Vector<PropertyInfo> pinfo;
8217
8218
for (const PropertyInfo &E : props) {
8219
for (int i = 0; i < properties.size(); i++) {
8220
if (E.name == String(properties[i])) {
8221
pinfo.push_back(E);
8222
}
8223
}
8224
}
8225
8226
if (pinfo.is_empty()) {
8227
return nullptr;
8228
}
8229
8230
properties.clear();
8231
8232
Ref<VisualShaderNode> node = p_node;
8233
Vector<EditorProperty *> editors;
8234
8235
for (int i = 0; i < pinfo.size(); i++) {
8236
EditorProperty *prop = EditorInspector::instantiate_property_editor(node.ptr(), pinfo[i].type, pinfo[i].name, pinfo[i].hint, pinfo[i].hint_string, pinfo[i].usage);
8237
if (!prop) {
8238
return nullptr;
8239
}
8240
8241
if (Object::cast_to<EditorPropertyResource>(prop)) {
8242
Object::cast_to<EditorPropertyResource>(prop)->set_use_sub_inspector(false);
8243
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8244
} else if (Object::cast_to<EditorPropertyTransform3D>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
8245
prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
8246
} else if (Object::cast_to<EditorPropertyVector4>(prop)) {
8247
prop->set_custom_minimum_size(Size2(320 * EDSCALE, 0));
8248
} else if (Object::cast_to<EditorPropertyFloat>(prop)) {
8249
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8250
} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
8251
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8252
Object::cast_to<EditorPropertyEnum>(prop)->set_option_button_clip(false);
8253
} else if (Object::cast_to<EditorPropertyColor>(prop)) {
8254
Object::cast_to<EditorPropertyColor>(prop)->set_live_changes_enabled(false);
8255
}
8256
8257
editors.push_back(prop);
8258
properties.push_back(pinfo[i].name);
8259
}
8260
VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor);
8261
editor->setup(vseditor, p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node);
8262
return editor;
8263
}
8264
8265
void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
8266
Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
8267
if (visual_shader->get_mode() == p_which) {
8268
return;
8269
}
8270
8271
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_editor_data().get_editor_by_name("Shader"));
8272
if (!shader_editor) {
8273
return;
8274
}
8275
VisualShaderEditor *editor = Object::cast_to<VisualShaderEditor>(shader_editor->get_shader_editor(visual_shader));
8276
if (!editor) {
8277
return;
8278
}
8279
8280
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
8281
undo_redo->create_action(TTR("Visual Shader Mode Changed"));
8282
//do is easy
8283
undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which);
8284
undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode());
8285
8286
undo_redo->add_do_method(editor, "_set_mode", p_which);
8287
undo_redo->add_undo_method(editor, "_set_mode", visual_shader->get_mode());
8288
8289
//now undo is hell
8290
8291
//1. restore connections to output
8292
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
8293
VisualShader::Type type = VisualShader::Type(i);
8294
List<VisualShader::Connection> conns;
8295
visual_shader->get_node_connections(type, &conns);
8296
for (const VisualShader::Connection &E : conns) {
8297
if (E.to_node == VisualShader::NODE_ID_OUTPUT) {
8298
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
8299
}
8300
}
8301
}
8302
//2. restore input indices
8303
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
8304
VisualShader::Type type = VisualShader::Type(i);
8305
Vector<int> nodes = visual_shader->get_node_list(type);
8306
for (int j = 0; j < nodes.size(); j++) {
8307
Ref<VisualShaderNodeInput> input = visual_shader->get_node(type, nodes[j]);
8308
if (input.is_null()) {
8309
continue;
8310
}
8311
8312
undo_redo->add_undo_method(input.ptr(), "set_input_name", input->get_input_name());
8313
}
8314
}
8315
8316
//3. restore enums and flags
8317
List<PropertyInfo> props;
8318
visual_shader->get_property_list(&props);
8319
8320
for (const PropertyInfo &E : props) {
8321
if (E.name.begins_with("flags/") || E.name.begins_with("modes/")) {
8322
undo_redo->add_undo_property(visual_shader.ptr(), E.name, visual_shader->get(E.name));
8323
}
8324
}
8325
8326
//4. delete varyings (if needed)
8327
if (p_which == VisualShader::MODE_PARTICLES || p_which == VisualShader::MODE_SKY || p_which == VisualShader::MODE_FOG || p_which == VisualShader::MODE_TEXTURE_BLIT) {
8328
int var_count = visual_shader->get_varyings_count();
8329
8330
if (var_count > 0) {
8331
for (int i = 0; i < var_count; i++) {
8332
const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
8333
undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", var->name);
8334
undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", var->name, var->mode, var->type);
8335
}
8336
8337
undo_redo->add_do_method(editor, "_update_varyings");
8338
undo_redo->add_undo_method(editor, "_update_varyings");
8339
}
8340
}
8341
8342
undo_redo->add_do_method(editor, "_update_nodes");
8343
undo_redo->add_undo_method(editor, "_update_nodes");
8344
8345
undo_redo->add_do_method(editor, "_update_graph");
8346
undo_redo->add_undo_method(editor, "_update_graph");
8347
8348
undo_redo->commit_action();
8349
}
8350
8351
void EditorPropertyVisualShaderMode::update_property() {
8352
int which = get_edited_property_value();
8353
options->select(which);
8354
}
8355
8356
void EditorPropertyVisualShaderMode::setup(const Vector<String> &p_options) {
8357
for (int i = 0; i < p_options.size(); i++) {
8358
options->add_item(p_options[i], i);
8359
}
8360
}
8361
8362
void EditorPropertyVisualShaderMode::set_option_button_clip(bool p_enable) {
8363
options->set_clip_text(p_enable);
8364
}
8365
8366
EditorPropertyVisualShaderMode::EditorPropertyVisualShaderMode() {
8367
options = memnew(OptionButton);
8368
options->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
8369
options->set_clip_text(true);
8370
add_child(options);
8371
add_focusable(options);
8372
options->connect(SceneStringName(item_selected), callable_mp(this, &EditorPropertyVisualShaderMode::_option_selected));
8373
}
8374
8375
bool EditorInspectorVisualShaderModePlugin::can_handle(Object *p_object) {
8376
return true; // Can handle everything.
8377
}
8378
8379
bool EditorInspectorVisualShaderModePlugin::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) {
8380
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
8381
EditorPropertyVisualShaderMode *mode_editor = memnew(EditorPropertyVisualShaderMode);
8382
Vector<String> options = p_hint_text.split(",");
8383
mode_editor->setup(options);
8384
add_property_editor(p_path, mode_editor);
8385
8386
return true;
8387
}
8388
8389
return false;
8390
}
8391
8392
//////////////////////////////////
8393
8394
void VisualShaderNodePortPreview::_shader_changed() {
8395
if (!is_valid || shader.is_null()) {
8396
return;
8397
}
8398
8399
Vector<VisualShader::DefaultTextureParam> default_textures;
8400
String shader_code = shader->generate_preview_shader(type, node, port, default_textures);
8401
8402
Ref<Shader> preview_shader;
8403
preview_shader.instantiate();
8404
preview_shader->set_code(shader_code);
8405
for (int i = 0; i < default_textures.size(); i++) {
8406
int j = 0;
8407
for (List<Ref<Texture>>::ConstIterator itr = default_textures[i].params.begin(); itr != default_textures[i].params.end(); ++itr, ++j) {
8408
preview_shader->set_default_texture_parameter(default_textures[i].name, *itr, j);
8409
}
8410
}
8411
8412
Ref<ShaderMaterial> mat;
8413
mat.instantiate();
8414
mat->set_shader(preview_shader);
8415
8416
if (preview_mat.is_valid() && preview_mat->get_shader().is_valid()) {
8417
List<PropertyInfo> params;
8418
preview_mat->get_shader()->get_shader_uniform_list(&params);
8419
for (const PropertyInfo &E : params) {
8420
mat->set_shader_parameter(E.name, preview_mat->get_shader_parameter(E.name));
8421
}
8422
}
8423
8424
set_material(mat);
8425
}
8426
8427
void VisualShaderNodePortPreview::setup(const Ref<VisualShader> &p_shader, Ref<ShaderMaterial> &p_preview_material, VisualShader::Type p_type, bool p_has_transparency, int p_node, int p_port, bool p_is_valid) {
8428
if (p_has_transparency) {
8429
checkerboard = memnew(TextureRect);
8430
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
8431
checkerboard->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
8432
checkerboard->set_draw_behind_parent(true);
8433
add_child(checkerboard);
8434
}
8435
8436
set_mouse_filter(MOUSE_FILTER_PASS);
8437
shader = p_shader;
8438
shader->connect_changed(callable_mp(this, &VisualShaderNodePortPreview::_shader_changed), CONNECT_DEFERRED);
8439
preview_mat = p_preview_material;
8440
type = p_type;
8441
port = p_port;
8442
node = p_node;
8443
is_valid = p_is_valid;
8444
queue_redraw();
8445
_shader_changed();
8446
}
8447
8448
Size2 VisualShaderNodePortPreview::get_minimum_size() const {
8449
int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
8450
return Size2(port_preview_size, port_preview_size) * EDSCALE;
8451
}
8452
8453
void VisualShaderNodePortPreview::_notification(int p_what) {
8454
switch (p_what) {
8455
case NOTIFICATION_THEME_CHANGED: {
8456
if (checkerboard != nullptr) {
8457
checkerboard->set_texture(get_theme_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
8458
}
8459
} break;
8460
case NOTIFICATION_DRAW: {
8461
Vector<Vector2> points = {
8462
Vector2(),
8463
Vector2(get_size().width, 0),
8464
get_size(),
8465
Vector2(0, get_size().height)
8466
};
8467
8468
Vector<Vector2> uvs = {
8469
Vector2(0, 0),
8470
Vector2(1, 0),
8471
Vector2(1, 1),
8472
Vector2(0, 1)
8473
};
8474
8475
if (is_valid) {
8476
Vector<Color> colors = {
8477
Color(1, 1, 1, 1),
8478
Color(1, 1, 1, 1),
8479
Color(1, 1, 1, 1),
8480
Color(1, 1, 1, 1)
8481
};
8482
draw_primitive(points, colors, uvs);
8483
} else {
8484
Vector<Color> colors = {
8485
Color(0, 0, 0, 1),
8486
Color(0, 0, 0, 1),
8487
Color(0, 0, 0, 1),
8488
Color(0, 0, 0, 1)
8489
};
8490
draw_primitive(points, colors, uvs);
8491
}
8492
8493
} break;
8494
}
8495
}
8496
8497
//////////////////////////////////
8498
8499
String VisualShaderConversionPlugin::converts_to() const {
8500
return "Shader";
8501
}
8502
8503
bool VisualShaderConversionPlugin::handles(const Ref<Resource> &p_resource) const {
8504
Ref<VisualShader> vshader = p_resource;
8505
return vshader.is_valid();
8506
}
8507
8508
Ref<Resource> VisualShaderConversionPlugin::convert(const Ref<Resource> &p_resource) const {
8509
Ref<VisualShader> vshader = p_resource;
8510
ERR_FAIL_COND_V(vshader.is_null(), Ref<Resource>());
8511
int embed = vshader->has_node_embeds();
8512
8513
EditorToaster *toast = EditorToaster::get_singleton();
8514
if (toast == nullptr) {
8515
ERR_FAIL_COND_V_MSG(embed == 2, Ref<Resource>(), "Cannot convert VisualShader to GDShader because VisualShader has embedded subresources.");
8516
if (embed == 1) {
8517
WARN_PRINT("Visual Shader conversion cannot convert external dependencies. Resource references from Nodes will have to be rebound as ShaderParameters on a Material.");
8518
}
8519
} else if (embed == 2) {
8520
toast->popup_str(TTR("Cannot convert VisualShader to GDShader because VisualShader has embedded subresources."), EditorToaster::SEVERITY_ERROR);
8521
return Ref<Resource>();
8522
} else if (embed == 1) {
8523
toast->popup_str(TTR("Visual Shader conversion cannot convert external dependencies. Resource references from Nodes will have to be rebound as ShaderParameters on a Material."), EditorToaster::SEVERITY_WARNING);
8524
}
8525
8526
Ref<Shader> shader;
8527
shader.instantiate();
8528
8529
String code = vshader->get_code();
8530
shader->set_code(code);
8531
8532
return shader;
8533
}
8534
8535