Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/shader/visual_shader_editor_plugin.cpp
9896 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/io/resource_loader.h"
35
#include "core/math/math_defs.h"
36
#include "core/os/keyboard.h"
37
#include "core/version_generated.gen.h"
38
#include "editor/docks/filesystem_dock.h"
39
#include "editor/docks/inspector_dock.h"
40
#include "editor/editor_node.h"
41
#include "editor/editor_string_names.h"
42
#include "editor/editor_undo_redo_manager.h"
43
#include "editor/file_system/editor_paths.h"
44
#include "editor/inspector/editor_properties.h"
45
#include "editor/inspector/editor_properties_vector.h"
46
#include "editor/scene/curve_editor_plugin.h"
47
#include "editor/scene/material_editor_plugin.h"
48
#include "editor/settings/editor_settings.h"
49
#include "editor/shader/shader_editor_plugin.h"
50
#include "editor/themes/editor_scale.h"
51
#include "editor/themes/editor_theme_manager.h"
52
#include "scene/animation/tween.h"
53
#include "scene/gui/button.h"
54
#include "scene/gui/check_box.h"
55
#include "scene/gui/code_edit.h"
56
#include "scene/gui/color_picker.h"
57
#include "scene/gui/flow_container.h"
58
#include "scene/gui/graph_edit.h"
59
#include "scene/gui/menu_button.h"
60
#include "scene/gui/option_button.h"
61
#include "scene/gui/popup.h"
62
#include "scene/gui/rich_text_label.h"
63
#include "scene/gui/separator.h"
64
#include "scene/gui/split_container.h"
65
#include "scene/gui/texture_rect.h"
66
#include "scene/gui/tree.h"
67
#include "scene/gui/view_panner.h"
68
#include "scene/main/window.h"
69
#include "scene/resources/curve_texture.h"
70
#include "scene/resources/style_box_flat.h"
71
#include "scene/resources/visual_shader_nodes.h"
72
#include "scene/resources/visual_shader_particle_nodes.h"
73
#include "servers/display_server.h"
74
#include "servers/rendering/shader_preprocessor.h"
75
#include "servers/rendering/shader_types.h"
76
77
struct FloatConstantDef {
78
String name;
79
float value = 0;
80
const char *desc_key;
81
};
82
83
static FloatConstantDef float_constant_defs[] = {
84
{ "E", Math::E, TTRC("E constant (2.718282). Represents the base of the natural logarithm.") },
85
{ "Epsilon", CMP_EPSILON, TTRC("Epsilon constant (0.00001). Smallest possible scalar number.") },
86
{ "Phi", 1.618034f, TTRC("Phi constant (1.618034). Golden ratio.") },
87
{ "Pi/4", Math::PI / 4, TTRC("Pi/4 constant (0.785398) or 45 degrees.") },
88
{ "Pi/2", Math::PI / 2, TTRC("Pi/2 constant (1.570796) or 90 degrees.") },
89
{ "Pi", Math::PI, TTRC("Pi constant (3.141593) or 180 degrees.") },
90
{ "Tau", Math::TAU, TTRC("Tau constant (6.283185) or 360 degrees.") },
91
{ "Sqrt2", Math::SQRT2, TTRC("Sqrt2 constant (1.414214). Square root of 2.") }
92
};
93
94
constexpr int MAX_FLOAT_CONST_DEFS = std::size(float_constant_defs);
95
96
///////////////////
97
98
void VisualShaderNodePlugin::set_editor(VisualShaderEditor *p_editor) {
99
vseditor = p_editor;
100
}
101
102
Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
103
Object *ret = nullptr;
104
GDVIRTUAL_CALL(_create_editor, p_parent_resource, p_node, ret);
105
return Object::cast_to<Control>(ret);
106
}
107
108
void VisualShaderNodePlugin::_bind_methods() {
109
GDVIRTUAL_BIND(_create_editor, "parent_resource", "visual_shader_node");
110
}
111
112
///////////////////
113
114
void VSGraphNode::_draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color, const Color &p_rim_color) {
115
Ref<Texture2D> port_icon = p_left ? get_slot_custom_icon_left(p_slot_index) : get_slot_custom_icon_right(p_slot_index);
116
117
Point2 icon_offset;
118
if (port_icon.is_null()) {
119
port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
120
}
121
122
icon_offset = -port_icon->get_size() * 0.5;
123
124
// Draw "shadow"/outline in the connection rim color.
125
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);
126
draw_texture_rect(port_icon, Rect2(p_pos + icon_offset * EDSCALE, port_icon->get_size() * EDSCALE), false, p_color);
127
}
128
129
void VSGraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
130
Color rim_color = get_theme_color(SNAME("connection_rim_color"), SNAME("GraphEdit"));
131
_draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
132
}
133
134
///////////////////
135
136
void VSRerouteNode::_notification(int p_what) {
137
switch (p_what) {
138
case NOTIFICATION_READY: {
139
connect(SceneStringName(mouse_entered), callable_mp(this, &VSRerouteNode::_on_mouse_entered));
140
connect(SceneStringName(mouse_exited), callable_mp(this, &VSRerouteNode::_on_mouse_exited));
141
} break;
142
case NOTIFICATION_DRAW: {
143
Vector2 offset = Vector2(0, -16 * EDSCALE);
144
Color drag_bg_color = get_theme_color(SNAME("drag_background"), SNAME("VSRerouteNode"));
145
draw_circle(get_size() * 0.5 + offset, 16 * EDSCALE, Color(drag_bg_color, selected ? 1 : icon_opacity), true, -1, true);
146
147
Ref<Texture2D> icon = get_editor_theme_icon(SNAME("ToolMove"));
148
Point2 icon_offset = -icon->get_size() * 0.5 + get_size() * 0.5 + offset;
149
draw_texture(icon, icon_offset, Color(1, 1, 1, selected ? 1 : icon_opacity));
150
} break;
151
}
152
}
153
154
void VSRerouteNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) {
155
Color rim_color = selected ? get_theme_color("selected_rim_color", "VSRerouteNode") : get_theme_color("connection_rim_color", "GraphEdit");
156
_draw_port(p_slot_index, p_pos, p_left, p_color, rim_color);
157
}
158
159
VSRerouteNode::VSRerouteNode() {
160
Label *title_lbl = Object::cast_to<Label>(get_titlebar_hbox()->get_child(0));
161
title_lbl->hide();
162
163
const Size2 size = Size2(32, 32) * EDSCALE;
164
165
Control *slot_area = memnew(Control);
166
slot_area->set_custom_minimum_size(size);
167
slot_area->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
168
add_child(slot_area);
169
170
// Lay the input and output ports on top of each other to create the illusion of a single port.
171
add_theme_constant_override("port_h_offset", size.width / 2);
172
}
173
174
void VSRerouteNode::set_icon_opacity(float p_opacity) {
175
icon_opacity = p_opacity;
176
queue_redraw();
177
}
178
179
void VSRerouteNode::_on_mouse_entered() {
180
Ref<Tween> tween = create_tween();
181
tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 0.0, 1.0, FADE_ANIMATION_LENGTH_SEC);
182
}
183
184
void VSRerouteNode::_on_mouse_exited() {
185
Ref<Tween> tween = create_tween();
186
tween->tween_method(callable_mp(this, &VSRerouteNode::set_icon_opacity), 1.0, 0.0, FADE_ANIMATION_LENGTH_SEC);
187
}
188
189
///////////////////
190
191
VisualShaderGraphPlugin::VisualShaderGraphPlugin() {
192
vs_msdf_fonts_theme.instantiate();
193
}
194
195
void VisualShaderGraphPlugin::_bind_methods() {
196
ClassDB::bind_method("add_node", &VisualShaderGraphPlugin::add_node);
197
ClassDB::bind_method("remove_node", &VisualShaderGraphPlugin::remove_node);
198
ClassDB::bind_method("connect_nodes", &VisualShaderGraphPlugin::connect_nodes);
199
ClassDB::bind_method("disconnect_nodes", &VisualShaderGraphPlugin::disconnect_nodes);
200
ClassDB::bind_method("set_node_position", &VisualShaderGraphPlugin::set_node_position);
201
ClassDB::bind_method("update_node", &VisualShaderGraphPlugin::update_node);
202
ClassDB::bind_method("update_node_deferred", &VisualShaderGraphPlugin::update_node_deferred);
203
ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value);
204
ClassDB::bind_method("set_parameter_name", &VisualShaderGraphPlugin::set_parameter_name);
205
ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression);
206
ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve);
207
ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz);
208
ClassDB::bind_method(D_METHOD("attach_node_to_frame", "type", "id", "frame"), &VisualShaderGraphPlugin::attach_node_to_frame);
209
ClassDB::bind_method(D_METHOD("detach_node_from_frame", "type", "id"), &VisualShaderGraphPlugin::detach_node_from_frame);
210
ClassDB::bind_method(D_METHOD("set_frame_color_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_color_enabled);
211
ClassDB::bind_method(D_METHOD("set_frame_color", "type", "id", "color"), &VisualShaderGraphPlugin::set_frame_color);
212
ClassDB::bind_method(D_METHOD("set_frame_autoshrink_enabled", "type", "id", "enabled"), &VisualShaderGraphPlugin::set_frame_autoshrink_enabled);
213
}
214
215
void VisualShaderGraphPlugin::set_editor(VisualShaderEditor *p_editor) {
216
editor = p_editor;
217
}
218
219
void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) {
220
visual_shader = Ref<VisualShader>(p_shader);
221
}
222
223
void VisualShaderGraphPlugin::set_connections(const List<VisualShader::Connection> &p_connections) {
224
connections = p_connections;
225
}
226
227
void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id, bool p_is_valid) {
228
if (editor->get_current_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].output_ports.has(p_port_id)) {
229
Link &link = links[p_node_id];
230
231
for (const KeyValue<int, Port> &E : link.output_ports) {
232
if (E.value.preview_button != nullptr) {
233
E.value.preview_button->set_pressed(false);
234
}
235
}
236
bool is_dirty = link.preview_pos < 0;
237
238
if (!is_dirty && link.preview_visible && link.preview_box != nullptr) {
239
link.graph_element->remove_child(link.preview_box);
240
memdelete(link.preview_box);
241
link.preview_box = nullptr;
242
link.graph_element->reset_size();
243
link.preview_visible = false;
244
}
245
246
if (p_port_id != -1 && link.output_ports[p_port_id].preview_button != nullptr) {
247
if (is_dirty) {
248
link.preview_pos = link.graph_element->get_child_count();
249
}
250
251
VBoxContainer *vbox = memnew(VBoxContainer);
252
link.graph_element->add_child(vbox);
253
link.graph_element->move_child(vbox, link.preview_pos);
254
255
GraphNode *graph_node = Object::cast_to<GraphNode>(link.graph_element);
256
if (graph_node) {
257
graph_node->set_slot_draw_stylebox(vbox->get_index(false), false);
258
}
259
260
Control *offset = memnew(Control);
261
offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
262
vbox->add_child(offset);
263
264
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
265
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);
266
port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
267
vbox->add_child(port_preview);
268
link.preview_visible = true;
269
link.preview_box = vbox;
270
link.output_ports[p_port_id].preview_button->set_pressed(true);
271
}
272
}
273
}
274
275
void VisualShaderGraphPlugin::update_node_deferred(VisualShader::Type p_type, int p_node_id) {
276
callable_mp(this, &VisualShaderGraphPlugin::update_node).call_deferred(p_type, p_node_id);
277
}
278
279
void VisualShaderGraphPlugin::update_node(VisualShader::Type p_type, int p_node_id) {
280
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id)) {
281
return;
282
}
283
remove_node(p_type, p_node_id, true);
284
add_node(p_type, p_node_id, true, true);
285
286
// TODO: Restore focus here?
287
}
288
289
void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, const Variant &p_value) {
290
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id)) {
291
return;
292
}
293
294
Button *button = links[p_node_id].input_ports[p_port_id].default_input_button;
295
296
switch (p_value.get_type()) {
297
case Variant::COLOR: {
298
button->set_custom_minimum_size(Size2(30, 0) * EDSCALE);
299
300
Callable ce = callable_mp(editor, &VisualShaderEditor::_draw_color_over_button);
301
if (!button->is_connected(SceneStringName(draw), ce)) {
302
button->connect(SceneStringName(draw), ce.bind(button, p_value));
303
}
304
} break;
305
case Variant::BOOL: {
306
button->set_text(((bool)p_value) ? "true" : "false");
307
} break;
308
case Variant::INT:
309
case Variant::FLOAT: {
310
button->set_text(String::num(p_value, 4));
311
} break;
312
case Variant::VECTOR2: {
313
Vector2 v = p_value;
314
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3));
315
} break;
316
case Variant::VECTOR3: {
317
Vector3 v = p_value;
318
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3));
319
} break;
320
case Variant::VECTOR4: {
321
Vector4 v = p_value;
322
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3) + "," + String::num(v.w, 3));
323
} break;
324
default: {
325
}
326
}
327
}
328
329
void VisualShaderGraphPlugin::set_parameter_name(VisualShader::Type p_type, int p_node_id, const String &p_name) {
330
if (editor->get_current_shader_type() == p_type && links.has(p_node_id) && links[p_node_id].parameter_name != nullptr) {
331
links[p_node_id].parameter_name->set_text(p_name);
332
}
333
}
334
335
void VisualShaderGraphPlugin::update_curve(int p_node_id) {
336
if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) {
337
Ref<VisualShaderNodeCurveTexture> tex = Object::cast_to<VisualShaderNodeCurveTexture>(links[p_node_id].visual_node);
338
ERR_FAIL_COND(tex.is_null());
339
340
if (tex->get_texture().is_valid()) {
341
links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve());
342
}
343
tex->emit_changed();
344
}
345
}
346
347
void VisualShaderGraphPlugin::update_curve_xyz(int p_node_id) {
348
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]) {
349
Ref<VisualShaderNodeCurveXYZTexture> tex = Object::cast_to<VisualShaderNodeCurveXYZTexture>(links[p_node_id].visual_node);
350
ERR_FAIL_COND(tex.is_null());
351
352
if (tex->get_texture().is_valid()) {
353
links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve_x());
354
links[p_node_id].curve_editors[1]->set_curve(tex->get_texture()->get_curve_y());
355
links[p_node_id].curve_editors[2]->set_curve(tex->get_texture()->get_curve_z());
356
}
357
tex->emit_changed();
358
}
359
}
360
361
int VisualShaderGraphPlugin::get_constant_index(float p_constant) const {
362
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
363
if (Math::is_equal_approx(p_constant, float_constant_defs[i].value)) {
364
return i + 1;
365
}
366
}
367
return 0;
368
}
369
370
void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression) {
371
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id) || !links[p_node_id].expression_edit) {
372
return;
373
}
374
links[p_node_id].expression_edit->set_text(p_expression);
375
}
376
377
void VisualShaderGraphPlugin::attach_node_to_frame(VisualShader::Type p_type, int p_node_id, int p_frame_id) {
378
if (p_type != editor->get_current_shader_type() || !links.has(p_node_id) || !links.has(p_frame_id)) {
379
return;
380
}
381
382
GraphEdit *graph = editor->graph;
383
if (!graph) {
384
return;
385
}
386
387
// Get the hint label and hide it before attaching the node to prevent resizing issues with the frame.
388
GraphFrame *frame = Object::cast_to<GraphFrame>(links[p_frame_id].graph_element);
389
ERR_FAIL_COND_MSG(!frame, "VisualShader node to attach to is not a frame node.");
390
391
Label *frame_hint_label = Object::cast_to<Label>(frame->get_child(0, false));
392
if (frame_hint_label) {
393
frame_hint_label->hide();
394
}
395
396
graph->attach_graph_element_to_frame(itos(p_node_id), itos(p_frame_id));
397
}
398
399
void VisualShaderGraphPlugin::detach_node_from_frame(VisualShader::Type p_type, int p_node_id) {
400
GraphEdit *graph = editor->graph;
401
if (!graph) {
402
return;
403
}
404
405
const StringName node_name = itos(p_node_id);
406
GraphFrame *frame = graph->get_element_frame(node_name);
407
if (!frame) {
408
return;
409
}
410
411
graph->detach_graph_element_from_frame(node_name);
412
413
bool no_more_frames_attached = graph->get_attached_nodes_of_frame(frame->get_name()).is_empty();
414
415
if (no_more_frames_attached) {
416
// Get the hint label and show it.
417
Label *frame_hint_label = Object::cast_to<Label>(frame->get_child(0, false));
418
ERR_FAIL_COND_MSG(!frame_hint_label, "Frame node does not have a hint label.");
419
420
frame_hint_label->show();
421
}
422
}
423
424
void VisualShaderGraphPlugin::set_frame_color_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable) {
425
GraphEdit *graph = editor->graph;
426
ERR_FAIL_COND(!graph);
427
428
const NodePath node_name = itos(p_node_id);
429
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
430
if (!frame) {
431
return;
432
}
433
434
frame->set_tint_color_enabled(p_enable);
435
}
436
437
void VisualShaderGraphPlugin::set_frame_color(VisualShader::Type p_type, int p_node_id, const Color &p_color) {
438
GraphEdit *graph = editor->graph;
439
ERR_FAIL_COND(!graph);
440
441
const NodePath node_name = itos(p_node_id);
442
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
443
if (!frame) {
444
return;
445
}
446
447
frame->set_tint_color(p_color);
448
}
449
450
void VisualShaderGraphPlugin::set_frame_autoshrink_enabled(VisualShader::Type p_type, int p_node_id, bool p_enable) {
451
GraphEdit *graph = editor->graph;
452
ERR_FAIL_COND(!graph);
453
454
const NodePath node_name = itos(p_node_id);
455
GraphFrame *frame = Object::cast_to<GraphFrame>(graph->get_node_or_null(node_name));
456
if (!frame) {
457
return;
458
}
459
460
frame->set_autoshrink_enabled(p_enable);
461
}
462
463
void VisualShaderGraphPlugin::update_reroute_nodes() {
464
for (const KeyValue<int, Link> &E : links) {
465
Ref<VisualShaderNodeReroute> reroute_node = Object::cast_to<VisualShaderNodeReroute>(E.value.visual_node);
466
if (reroute_node.is_valid()) {
467
update_node(editor->get_current_shader_type(), E.key);
468
}
469
}
470
}
471
472
Ref<Script> VisualShaderGraphPlugin::get_node_script(int p_node_id) const {
473
if (!links.has(p_node_id)) {
474
return Ref<Script>();
475
}
476
477
Ref<VisualShaderNodeCustom> custom = Ref<VisualShaderNodeCustom>(links[p_node_id].visual_node);
478
if (custom.is_valid()) {
479
return custom->get_script();
480
}
481
482
return Ref<Script>();
483
}
484
485
void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) {
486
links[p_node_id].input_ports.insert(p_port_id, { p_button });
487
}
488
489
void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *p_expression_edit) {
490
links[p_node_id].expression_edit = p_expression_edit;
491
}
492
493
void VisualShaderGraphPlugin::register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor) {
494
links[p_node_id].curve_editors[p_index] = p_curve_editor;
495
}
496
497
void VisualShaderGraphPlugin::update_parameter_refs() {
498
for (KeyValue<int, Link> &E : links) {
499
VisualShaderNodeParameterRef *ref = Object::cast_to<VisualShaderNodeParameterRef>(E.value.visual_node);
500
if (ref) {
501
remove_node(E.value.type, E.key, true);
502
add_node(E.value.type, E.key, true, true);
503
}
504
}
505
}
506
507
// Only updates the linked frames of the given node, not the node itself (in case it's a frame node).
508
void VisualShaderGraphPlugin::update_frames(VisualShader::Type p_type, int p_node) {
509
GraphEdit *graph = editor->graph;
510
if (!graph) {
511
return;
512
}
513
514
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_node);
515
if (vsnode.is_null()) {
516
WARN_PRINT("Update linked frames: Node not found.");
517
return;
518
}
519
520
int frame_vsnode_id = vsnode->get_frame();
521
if (frame_vsnode_id == -1) {
522
return;
523
}
524
525
Ref<VisualShaderNodeFrame> frame_node = visual_shader->get_node(p_type, frame_vsnode_id);
526
if (frame_node.is_null() || !links.has(frame_vsnode_id)) {
527
return;
528
}
529
530
GraphFrame *frame = Object::cast_to<GraphFrame>(links[frame_vsnode_id].graph_element);
531
if (!frame) {
532
return;
533
}
534
535
// Update the frame node recursively.
536
editor->graph->_update_graph_frame(frame);
537
}
538
539
void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) {
540
if (editor->get_current_shader_type() == p_type && links.has(p_id)) {
541
links[p_id].graph_element->set_position_offset(p_position);
542
}
543
}
544
545
bool VisualShaderGraphPlugin::is_preview_visible(int p_id) const {
546
return links[p_id].preview_visible;
547
}
548
549
void VisualShaderGraphPlugin::clear_links() {
550
links.clear();
551
}
552
553
void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphElement *p_graph_element) {
554
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 } });
555
}
556
557
void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, VisualShaderNode::PortType p_port_type, TextureButton *p_button) {
558
links[p_node_id].output_ports.insert(p_port, { p_port_type, p_button });
559
}
560
561
void VisualShaderGraphPlugin::register_parameter_name(int p_node_id, LineEdit *p_parameter_name) {
562
links[p_node_id].parameter_name = p_parameter_name;
563
}
564
565
void VisualShaderGraphPlugin::update_theme() {
566
vector_expanded_color[0] = editor->get_theme_color(SNAME("axis_x_color"), EditorStringName(Editor)); // red
567
vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), EditorStringName(Editor)); // green
568
vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), EditorStringName(Editor)); // blue
569
vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), EditorStringName(Editor)); // alpha
570
571
Ref<Font> label_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_msdf", EditorStringName(EditorFonts));
572
Ref<Font> label_bold_font = EditorNode::get_singleton()->get_editor_theme()->get_font("main_bold_msdf", EditorStringName(EditorFonts));
573
vs_msdf_fonts_theme->set_font(SceneStringName(font), "Label", label_font);
574
vs_msdf_fonts_theme->set_font(SceneStringName(font), "GraphNodeTitleLabel", label_bold_font);
575
if (!EditorThemeManager::is_dark_theme()) {
576
// Override the color to white for light themes.
577
vs_msdf_fonts_theme->set_color(SceneStringName(font_color), "GraphNodeTitleLabel", Color(1, 1, 1));
578
}
579
vs_msdf_fonts_theme->set_font(SceneStringName(font), "LineEdit", label_font);
580
vs_msdf_fonts_theme->set_font(SceneStringName(font), "Button", label_font);
581
}
582
583
bool VisualShaderGraphPlugin::is_node_has_parameter_instances_relatively(VisualShader::Type p_type, int p_node) const {
584
bool result = false;
585
586
Ref<VisualShaderNodeParameter> parameter_node = Object::cast_to<VisualShaderNodeParameter>(visual_shader->get_node_unchecked(p_type, p_node).ptr());
587
if (parameter_node.is_valid()) {
588
if (parameter_node->get_qualifier() == VisualShaderNodeParameter::QUAL_INSTANCE) {
589
return true;
590
}
591
}
592
593
const LocalVector<int> &prev_connected_nodes = visual_shader->get_prev_connected_nodes(p_type, p_node);
594
595
for (const int &E : prev_connected_nodes) {
596
result = is_node_has_parameter_instances_relatively(p_type, E);
597
if (result) {
598
break;
599
}
600
}
601
602
return result;
603
}
604
605
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id, bool p_just_update, bool p_update_frames) {
606
if (visual_shader.is_null() || p_type != editor->get_current_shader_type()) {
607
return;
608
}
609
GraphEdit *graph = editor->graph;
610
if (!graph) {
611
return;
612
}
613
VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
614
if (!graph_plugin) {
615
return;
616
}
617
Shader::Mode mode = visual_shader->get_mode();
618
619
Control *offset;
620
621
const Color type_color[] = {
622
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
623
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
624
EDITOR_GET("editors/visual_editors/connection_colors/scalar_color"),
625
EDITOR_GET("editors/visual_editors/connection_colors/vector2_color"),
626
EDITOR_GET("editors/visual_editors/connection_colors/vector3_color"),
627
EDITOR_GET("editors/visual_editors/connection_colors/vector4_color"),
628
EDITOR_GET("editors/visual_editors/connection_colors/boolean_color"),
629
EDITOR_GET("editors/visual_editors/connection_colors/transform_color"),
630
EDITOR_GET("editors/visual_editors/connection_colors/sampler_color"),
631
};
632
633
// Keep in sync with VisualShaderNode::Category.
634
const Color category_color[VisualShaderNode::Category::CATEGORY_MAX] = {
635
Color(0.0, 0.0, 0.0), // None (default, not used)
636
EDITOR_GET("editors/visual_editors/category_colors/output_color"),
637
EDITOR_GET("editors/visual_editors/category_colors/color_color"),
638
EDITOR_GET("editors/visual_editors/category_colors/conditional_color"),
639
EDITOR_GET("editors/visual_editors/category_colors/input_color"),
640
EDITOR_GET("editors/visual_editors/category_colors/scalar_color"),
641
EDITOR_GET("editors/visual_editors/category_colors/textures_color"),
642
EDITOR_GET("editors/visual_editors/category_colors/transform_color"),
643
EDITOR_GET("editors/visual_editors/category_colors/utility_color"),
644
EDITOR_GET("editors/visual_editors/category_colors/vector_color"),
645
EDITOR_GET("editors/visual_editors/category_colors/special_color"),
646
EDITOR_GET("editors/visual_editors/category_colors/particle_color"),
647
};
648
649
static const String vector_expanded_name[4] = { "red", "green", "blue", "alpha" };
650
651
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
652
ERR_FAIL_COND(vsnode.is_null());
653
654
Ref<VisualShaderNodeResizableBase> resizable_node = vsnode;
655
bool is_resizable = resizable_node.is_valid();
656
Size2 size = Size2(0, 0);
657
658
Ref<VisualShaderNodeGroupBase> group_node = vsnode;
659
bool is_group = group_node.is_valid();
660
661
Ref<VisualShaderNodeFrame> frame_node = vsnode;
662
bool is_frame = frame_node.is_valid();
663
664
Ref<VisualShaderNodeExpression> expression_node = group_node;
665
bool is_expression = expression_node.is_valid();
666
String expression = "";
667
668
Ref<VisualShaderNodeReroute> reroute_node = vsnode;
669
bool is_reroute = reroute_node.is_valid();
670
671
Ref<VisualShaderNodeCustom> custom_node = vsnode;
672
if (custom_node.is_valid()) {
673
custom_node->_set_initialized(true);
674
}
675
676
GraphElement *node;
677
if (is_frame) {
678
GraphFrame *frame = memnew(GraphFrame);
679
frame->set_title(vsnode->get_caption());
680
node = frame;
681
} else if (is_reroute) {
682
VSRerouteNode *reroute_gnode = memnew(VSRerouteNode);
683
reroute_gnode->set_ignore_invalid_connection_type(true);
684
node = reroute_gnode;
685
} else {
686
VSGraphNode *gnode = memnew(VSGraphNode);
687
gnode->set_title(vsnode->get_caption());
688
node = gnode;
689
}
690
node->set_name(itos(p_id));
691
692
// All nodes are closable except the output node.
693
if (p_id >= 2) {
694
vsnode->set_deletable(true);
695
node->connect("delete_request", callable_mp(editor, &VisualShaderEditor::_delete_node_request).bind(p_type, p_id), CONNECT_DEFERRED);
696
}
697
graph->add_child(node);
698
node->set_theme(vs_msdf_fonts_theme);
699
700
// Set the node's titlebar color based on its category.
701
if (vsnode->get_category() != VisualShaderNode::CATEGORY_NONE && !is_frame && !is_reroute) {
702
Ref<StyleBoxFlat> sb_colored = editor->get_theme_stylebox("titlebar", "GraphNode")->duplicate();
703
sb_colored->set_bg_color(category_color[vsnode->get_category()]);
704
node->add_theme_style_override("titlebar", sb_colored);
705
706
Ref<StyleBoxFlat> sb_colored_selected = editor->get_theme_stylebox("titlebar_selected", "GraphNode")->duplicate();
707
sb_colored_selected->set_bg_color(category_color[vsnode->get_category()].lightened(0.2));
708
node->add_theme_style_override("titlebar_selected", sb_colored_selected);
709
}
710
711
if (p_just_update) {
712
Link &link = links[p_id];
713
714
link.visual_node = vsnode.ptr();
715
link.graph_element = node;
716
link.preview_box = nullptr;
717
link.preview_pos = -1;
718
link.output_ports.clear();
719
link.input_ports.clear();
720
} else {
721
register_link(p_type, p_id, vsnode.ptr(), node);
722
}
723
724
if (is_resizable) {
725
size = resizable_node->get_size();
726
727
node->set_resizable(true);
728
node->connect("resize_end", callable_mp(editor, &VisualShaderEditor::_node_resized).bind((int)p_type, p_id));
729
node->set_size(size);
730
// node->call_deferred(SNAME("set_size"), size);
731
// editor->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size);
732
}
733
734
if (is_expression) {
735
expression = expression_node->get_expression();
736
}
737
738
node->set_position_offset(visual_shader->get_node_position(p_type, p_id));
739
740
node->connect("dragged", callable_mp(editor, &VisualShaderEditor::_node_dragged).bind(p_id));
741
742
Control *custom_editor = nullptr;
743
int port_offset = 1;
744
745
if (p_update_frames) {
746
if (vsnode->get_frame() > -1) {
747
graph->attach_graph_element_to_frame(itos(p_id), itos(vsnode->get_frame()));
748
} else {
749
graph->detach_graph_element_from_frame(itos(p_id));
750
}
751
}
752
753
if (is_frame) {
754
GraphFrame *graph_frame = Object::cast_to<GraphFrame>(node);
755
ERR_FAIL_NULL(graph_frame);
756
757
graph_frame->set_tint_color_enabled(frame_node->is_tint_color_enabled());
758
graph_frame->set_tint_color(frame_node->get_tint_color());
759
760
// Add hint label.
761
Label *frame_hint_label = memnew(Label);
762
frame_hint_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
763
node->add_child(frame_hint_label);
764
frame_hint_label->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_CENTER);
765
frame_hint_label->set_vertical_alignment(VerticalAlignment::VERTICAL_ALIGNMENT_CENTER);
766
frame_hint_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
767
frame_hint_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
768
frame_hint_label->set_text(TTR("Drag and drop nodes here to attach them."));
769
frame_hint_label->set_modulate(Color(1.0, 1.0, 1.0, 0.3));
770
graph_frame->set_autoshrink_enabled(frame_node->is_autoshrink_enabled());
771
772
if (frame_node->get_attached_nodes().is_empty()) {
773
frame_hint_label->show();
774
} else {
775
frame_hint_label->hide();
776
}
777
778
// Attach all nodes.
779
if (p_update_frames && frame_node->get_attached_nodes().size() > 0) {
780
for (const int &id : frame_node->get_attached_nodes()) {
781
graph->attach_graph_element_to_frame(itos(id), node->get_name());
782
}
783
}
784
785
// We should be done here.
786
return;
787
}
788
789
if (!is_reroute) {
790
Control *content_offset = memnew(Control);
791
content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
792
node->add_child(content_offset);
793
}
794
795
if (is_group) {
796
port_offset += 1;
797
}
798
799
// Set the minimum width of a node based on the preview size to avoid a resize when toggling the preview.
800
Ref<StyleBoxFlat> graph_node_stylebox = graph->get_theme_stylebox(SceneStringName(panel), "GraphNode");
801
int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
802
if (!is_frame && !is_reroute) {
803
node->set_custom_minimum_size(Size2((Math::ceil(graph_node_stylebox->get_minimum_size().width) + port_preview_size) * EDSCALE, 0));
804
}
805
806
Ref<VisualShaderNodeParticleEmit> emit = vsnode;
807
if (emit.is_valid()) {
808
node->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
809
}
810
811
Ref<VisualShaderNodeParameterRef> parameter_ref = vsnode;
812
if (parameter_ref.is_valid()) {
813
parameter_ref->set_shader_rid(visual_shader->get_rid());
814
parameter_ref->update_parameter_type();
815
}
816
817
Ref<VisualShaderNodeVarying> varying = vsnode;
818
if (varying.is_valid()) {
819
varying->set_shader_rid(visual_shader->get_rid());
820
}
821
822
Ref<VisualShaderNodeParameter> parameter = vsnode;
823
HBoxContainer *hb = nullptr;
824
825
if (parameter.is_valid()) {
826
LineEdit *parameter_name = memnew(LineEdit);
827
register_parameter_name(p_id, parameter_name);
828
parameter_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
829
parameter_name->set_text(parameter->get_parameter_name());
830
parameter_name->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_parameter_line_edit_changed).bind(p_id));
831
parameter_name->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_parameter_line_edit_focus_out).bind(parameter_name, p_id));
832
833
if (vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
834
hb = memnew(HBoxContainer);
835
hb->add_child(parameter_name);
836
node->add_child(hb);
837
} else {
838
node->add_child(parameter_name);
839
}
840
port_offset++;
841
}
842
843
for (int i = 0; i < editor->plugins.size(); i++) {
844
vsnode->set_meta("id", p_id);
845
vsnode->set_meta("shader_type", (int)p_type);
846
custom_editor = editor->plugins.write[i]->create_editor(visual_shader, vsnode);
847
vsnode->remove_meta("id");
848
vsnode->remove_meta("shader_type");
849
if (custom_editor) {
850
if (vsnode->is_show_prop_names()) {
851
custom_editor->call_deferred(SNAME("_show_prop_names"), true);
852
}
853
break;
854
}
855
}
856
857
if (custom_node.is_valid()) {
858
bool first = true;
859
VBoxContainer *vbox = nullptr;
860
861
int i = 0;
862
for (List<VisualShaderNodeCustom::DropDownListProperty>::ConstIterator itr = custom_node->dp_props.begin(); itr != custom_node->dp_props.end(); ++itr, ++i) {
863
const VisualShaderNodeCustom::DropDownListProperty &dp = *itr;
864
865
if (first) {
866
first = false;
867
vbox = memnew(VBoxContainer);
868
node->add_child(vbox);
869
port_offset++;
870
}
871
872
HBoxContainer *hbox = memnew(HBoxContainer);
873
vbox->add_child(hbox);
874
hbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
875
876
String prop_name = dp.name.strip_edges();
877
if (!prop_name.is_empty()) {
878
Label *label = memnew(Label);
879
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
880
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
881
label->set_text(prop_name + ":");
882
hbox->add_child(label);
883
}
884
885
OptionButton *op = memnew(OptionButton);
886
hbox->add_child(op);
887
op->set_h_size_flags(Control::SIZE_EXPAND_FILL);
888
op->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_set_custom_node_option).bind(p_id, i), CONNECT_DEFERRED);
889
890
for (const String &s : dp.options) {
891
op->add_item(s);
892
}
893
if (custom_node->dp_selected_cache.has(i)) {
894
op->select(custom_node->dp_selected_cache[i]);
895
} else {
896
op->select(0);
897
}
898
}
899
}
900
901
Ref<VisualShaderNodeCurveTexture> curve = vsnode;
902
Ref<VisualShaderNodeCurveXYZTexture> curve_xyz = vsnode;
903
904
bool is_curve = curve.is_valid() || curve_xyz.is_valid();
905
if (is_curve) {
906
hb = memnew(HBoxContainer);
907
node->add_child(hb);
908
}
909
910
if (curve.is_valid()) {
911
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
912
913
if (curve->get_texture().is_valid()) {
914
curve->get_texture()->connect_changed(callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve).bind(p_id));
915
}
916
917
CurveEditor *curve_editor = memnew(CurveEditor);
918
node->add_child(curve_editor);
919
register_curve_editor(p_id, 0, curve_editor);
920
curve_editor->set_custom_minimum_size(Size2(300, 0));
921
curve_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
922
if (curve->get_texture().is_valid()) {
923
curve_editor->set_curve(curve->get_texture()->get_curve());
924
}
925
}
926
927
if (curve_xyz.is_valid()) {
928
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
929
930
if (curve_xyz->get_texture().is_valid()) {
931
curve_xyz->get_texture()->connect_changed(callable_mp(graph_plugin, &VisualShaderGraphPlugin::update_curve_xyz).bind(p_id));
932
}
933
934
CurveEditor *curve_editor_x = memnew(CurveEditor);
935
node->add_child(curve_editor_x);
936
register_curve_editor(p_id, 0, curve_editor_x);
937
curve_editor_x->set_custom_minimum_size(Size2(300, 0));
938
curve_editor_x->set_h_size_flags(Control::SIZE_EXPAND_FILL);
939
if (curve_xyz->get_texture().is_valid()) {
940
curve_editor_x->set_curve(curve_xyz->get_texture()->get_curve_x());
941
}
942
943
CurveEditor *curve_editor_y = memnew(CurveEditor);
944
node->add_child(curve_editor_y);
945
register_curve_editor(p_id, 1, curve_editor_y);
946
curve_editor_y->set_custom_minimum_size(Size2(300, 0));
947
curve_editor_y->set_h_size_flags(Control::SIZE_EXPAND_FILL);
948
if (curve_xyz->get_texture().is_valid()) {
949
curve_editor_y->set_curve(curve_xyz->get_texture()->get_curve_y());
950
}
951
952
CurveEditor *curve_editor_z = memnew(CurveEditor);
953
node->add_child(curve_editor_z);
954
register_curve_editor(p_id, 2, curve_editor_z);
955
curve_editor_z->set_custom_minimum_size(Size2(300, 0));
956
curve_editor_z->set_h_size_flags(Control::SIZE_EXPAND_FILL);
957
if (curve_xyz->get_texture().is_valid()) {
958
curve_editor_z->set_curve(curve_xyz->get_texture()->get_curve_z());
959
}
960
}
961
962
if (custom_editor) {
963
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) == ""))) {
964
// Will be embedded in first port.
965
} else {
966
port_offset++;
967
node->add_child(custom_editor);
968
custom_editor = nullptr;
969
}
970
}
971
972
if (is_group) {
973
if (group_node->is_editable()) {
974
HBoxContainer *hb2 = memnew(HBoxContainer);
975
976
String input_port_name = "input" + itos(group_node->get_free_input_port_id());
977
String output_port_name = "output" + itos(group_node->get_free_output_port_id());
978
979
for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) {
980
if (i < vsnode->get_input_port_count()) {
981
if (input_port_name == vsnode->get_input_port_name(i)) {
982
input_port_name = "_" + input_port_name;
983
}
984
}
985
if (i < vsnode->get_output_port_count()) {
986
if (output_port_name == vsnode->get_output_port_name(i)) {
987
output_port_name = "_" + output_port_name;
988
}
989
}
990
}
991
992
Button *add_input_btn = memnew(Button);
993
add_input_btn->set_text(TTR("Add Input"));
994
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);
995
hb2->add_child(add_input_btn);
996
997
hb2->add_spacer();
998
999
Button *add_output_btn = memnew(Button);
1000
add_output_btn->set_text(TTR("Add Output"));
1001
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);
1002
hb2->add_child(add_output_btn);
1003
1004
node->add_child(hb2);
1005
}
1006
}
1007
1008
int output_port_count = 0;
1009
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
1010
if (vsnode->_is_output_port_expanded(i)) {
1011
switch (vsnode->get_output_port_type(i)) {
1012
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1013
output_port_count += 2;
1014
} break;
1015
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1016
output_port_count += 3;
1017
} break;
1018
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1019
output_port_count += 4;
1020
} break;
1021
default:
1022
break;
1023
}
1024
}
1025
output_port_count++;
1026
}
1027
int max_ports = MAX(vsnode->get_input_port_count(), output_port_count);
1028
VisualShaderNode::PortType expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1029
int expanded_port_counter = 0;
1030
1031
for (int i = 0, j = 0; i < max_ports; i++, j++) {
1032
switch (expanded_type) {
1033
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1034
if (expanded_port_counter >= 2) {
1035
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1036
expanded_port_counter = 0;
1037
i -= 2;
1038
}
1039
} break;
1040
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1041
if (expanded_port_counter >= 3) {
1042
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1043
expanded_port_counter = 0;
1044
i -= 3;
1045
}
1046
} break;
1047
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1048
if (expanded_port_counter >= 4) {
1049
expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
1050
expanded_port_counter = 0;
1051
i -= 4;
1052
}
1053
} break;
1054
default:
1055
break;
1056
}
1057
1058
if (vsnode->is_port_separator(i)) {
1059
node->add_child(memnew(HSeparator));
1060
port_offset++;
1061
}
1062
1063
bool valid_left = j < vsnode->get_input_port_count();
1064
VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1065
bool port_left_used = false;
1066
String name_left;
1067
if (valid_left) {
1068
name_left = vsnode->get_input_port_name(j);
1069
port_left = vsnode->get_input_port_type(j);
1070
for (const VisualShader::Connection &E : connections) {
1071
if (E.to_node == p_id && E.to_port == j) {
1072
port_left_used = true;
1073
break;
1074
}
1075
}
1076
}
1077
1078
bool valid_right = true;
1079
VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR;
1080
String name_right;
1081
1082
if (expanded_type == VisualShaderNode::PORT_TYPE_SCALAR) {
1083
valid_right = i < vsnode->get_output_port_count();
1084
if (valid_right) {
1085
name_right = vsnode->get_output_port_name(i);
1086
port_right = vsnode->get_output_port_type(i);
1087
}
1088
} else {
1089
name_right = vector_expanded_name[expanded_port_counter++];
1090
}
1091
1092
bool is_first_hbox = false;
1093
if (i == 0 && hb != nullptr) {
1094
is_first_hbox = true;
1095
} else {
1096
hb = memnew(HBoxContainer);
1097
}
1098
hb->add_theme_constant_override("separation", 7 * EDSCALE);
1099
1100
// Default value button/property editor.
1101
Variant default_value;
1102
1103
if (valid_left && !port_left_used) {
1104
default_value = vsnode->get_input_port_default_value(j);
1105
}
1106
1107
Button *default_input_btn = memnew(Button);
1108
hb->add_child(default_input_btn);
1109
register_default_input_button(p_id, j, default_input_btn);
1110
default_input_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_edit_port_default_input).bind(default_input_btn, p_id, j));
1111
if (default_value.get_type() != Variant::NIL) { // only a label
1112
set_input_port_default_value(p_type, p_id, j, default_value);
1113
} else {
1114
default_input_btn->hide();
1115
}
1116
1117
if (j == 0 && custom_editor) {
1118
hb->add_child(custom_editor);
1119
custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1120
} else {
1121
if (valid_left) {
1122
if (is_group) {
1123
OptionButton *type_box = memnew(OptionButton);
1124
hb->add_child(type_box);
1125
type_box->add_item(TTR("Float"));
1126
type_box->add_item(TTR("Int"));
1127
type_box->add_item(TTR("UInt"));
1128
type_box->add_item(TTR("Vector2"));
1129
type_box->add_item(TTR("Vector3"));
1130
type_box->add_item(TTR("Vector4"));
1131
type_box->add_item(TTR("Boolean"));
1132
type_box->add_item(TTR("Transform"));
1133
type_box->add_item(TTR("Sampler"));
1134
type_box->select(group_node->get_input_port_type(j));
1135
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
1136
type_box->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_change_input_port_type).bind(p_id, j), CONNECT_DEFERRED);
1137
1138
LineEdit *name_box = memnew(LineEdit);
1139
hb->add_child(name_box);
1140
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
1141
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1142
name_box->set_text(name_left);
1143
name_box->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_change_input_port_name).bind(name_box, p_id, j), CONNECT_DEFERRED);
1144
name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, j, false), CONNECT_DEFERRED);
1145
1146
Button *remove_btn = memnew(Button);
1147
remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
1148
remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left);
1149
remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, j), CONNECT_DEFERRED);
1150
hb->add_child(remove_btn);
1151
} else {
1152
Label *label = memnew(Label);
1153
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1154
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
1155
label->set_text(name_left);
1156
label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
1157
hb->add_child(label);
1158
1159
if (vsnode->is_input_port_default(j, mode) && !port_left_used) {
1160
Label *hint_label = memnew(Label);
1161
hint_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1162
hint_label->set_text(TTR("[default]"));
1163
hint_label->add_theme_color_override(SceneStringName(font_color), editor->get_theme_color(SNAME("font_readonly_color"), SNAME("TextEdit")));
1164
hint_label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor")));
1165
hb->add_child(hint_label);
1166
}
1167
}
1168
}
1169
1170
if (!is_group && !is_first_hbox) {
1171
hb->add_spacer();
1172
}
1173
1174
if (valid_right) {
1175
if (is_group) {
1176
Button *remove_btn = memnew(Button);
1177
remove_btn->set_button_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
1178
remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left);
1179
remove_btn->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED);
1180
hb->add_child(remove_btn);
1181
1182
LineEdit *name_box = memnew(LineEdit);
1183
hb->add_child(name_box);
1184
name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0));
1185
name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
1186
name_box->set_text(name_right);
1187
name_box->connect(SceneStringName(text_submitted), callable_mp(editor, &VisualShaderEditor::_change_output_port_name).bind(name_box, p_id, i), CONNECT_DEFERRED);
1188
name_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_port_name_focus_out).bind(name_box, p_id, i, true), CONNECT_DEFERRED);
1189
1190
OptionButton *type_box = memnew(OptionButton);
1191
hb->add_child(type_box);
1192
type_box->add_item(TTR("Float"));
1193
type_box->add_item(TTR("Int"));
1194
type_box->add_item(TTR("UInt"));
1195
type_box->add_item(TTR("Vector2"));
1196
type_box->add_item(TTR("Vector3"));
1197
type_box->add_item(TTR("Vector4"));
1198
type_box->add_item(TTR("Boolean"));
1199
type_box->add_item(TTR("Transform"));
1200
type_box->select(group_node->get_output_port_type(i));
1201
type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
1202
type_box->connect(SceneStringName(item_selected), callable_mp(editor, &VisualShaderEditor::_change_output_port_type).bind(p_id, i), CONNECT_DEFERRED);
1203
} else {
1204
Label *label = memnew(Label);
1205
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1206
label->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
1207
label->set_text(name_right);
1208
label->add_theme_style_override(CoreStringName(normal), editor->get_theme_stylebox(SNAME("label_style"), SNAME("VShaderEditor"))); //more compact
1209
hb->add_child(label);
1210
}
1211
}
1212
}
1213
1214
if (valid_right) {
1215
if (expanded_port_counter == 0 && vsnode->is_output_port_expandable(i)) {
1216
TextureButton *expand = memnew(TextureButton);
1217
expand->set_accessibility_name(TTRC("Expand output port"));
1218
expand->set_toggle_mode(true);
1219
expand->set_texture_normal(editor->get_editor_theme_icon(SNAME("GuiTreeArrowRight")));
1220
expand->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiTreeArrowDown")));
1221
expand->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
1222
expand->set_pressed(vsnode->_is_output_port_expanded(i));
1223
expand->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_expand_output_port).bind(p_id, i, !vsnode->_is_output_port_expanded(i)), CONNECT_DEFERRED);
1224
hb->add_child(expand);
1225
}
1226
if (vsnode->has_output_port_preview(i) && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) {
1227
TextureButton *preview = memnew(TextureButton);
1228
preview->set_accessibility_name(TTRC("Select preview port"));
1229
preview->set_toggle_mode(true);
1230
preview->set_texture_normal(editor->get_editor_theme_icon(SNAME("GuiVisibilityHidden")));
1231
preview->set_texture_pressed(editor->get_editor_theme_icon(SNAME("GuiVisibilityVisible")));
1232
preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
1233
1234
register_output_port(p_id, j, port_right, preview);
1235
1236
preview->connect(SceneStringName(pressed), callable_mp(editor, &VisualShaderEditor::_preview_select_port).bind(p_id, j), CONNECT_DEFERRED);
1237
hb->add_child(preview);
1238
}
1239
}
1240
1241
if (is_group) {
1242
offset = memnew(Control);
1243
offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
1244
node->add_child(offset);
1245
port_offset++;
1246
}
1247
1248
if (!is_first_hbox && !is_reroute) {
1249
node->add_child(hb);
1250
if (curve_xyz.is_valid()) {
1251
node->move_child(hb, 1 + expanded_port_counter);
1252
}
1253
}
1254
1255
if (expanded_type != VisualShaderNode::PORT_TYPE_SCALAR) {
1256
continue;
1257
}
1258
1259
int idx = is_first_hbox ? 1 : i + port_offset;
1260
if (is_reroute) {
1261
idx = 0;
1262
}
1263
if (!is_frame) {
1264
GraphNode *graph_node = Object::cast_to<GraphNode>(node);
1265
1266
graph_node->set_slot(idx, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
1267
1268
if (vsnode->_is_output_port_expanded(i)) {
1269
switch (vsnode->get_output_port_type(i)) {
1270
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
1271
port_offset++;
1272
valid_left = (i + 1) < vsnode->get_input_port_count();
1273
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1274
if (valid_left) {
1275
port_left = vsnode->get_input_port_type(i + 1);
1276
}
1277
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1278
port_offset++;
1279
1280
valid_left = (i + 2) < vsnode->get_input_port_count();
1281
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1282
if (valid_left) {
1283
port_left = vsnode->get_input_port_type(i + 2);
1284
}
1285
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1286
1287
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_2D;
1288
} break;
1289
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
1290
port_offset++;
1291
valid_left = (i + 1) < vsnode->get_input_port_count();
1292
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1293
if (valid_left) {
1294
port_left = vsnode->get_input_port_type(i + 1);
1295
}
1296
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1297
port_offset++;
1298
1299
valid_left = (i + 2) < vsnode->get_input_port_count();
1300
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1301
if (valid_left) {
1302
port_left = vsnode->get_input_port_type(i + 2);
1303
}
1304
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1305
port_offset++;
1306
1307
valid_left = (i + 3) < vsnode->get_input_port_count();
1308
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1309
if (valid_left) {
1310
port_left = vsnode->get_input_port_type(i + 3);
1311
}
1312
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
1313
1314
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_3D;
1315
} break;
1316
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
1317
port_offset++;
1318
valid_left = (i + 1) < vsnode->get_input_port_count();
1319
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1320
if (valid_left) {
1321
port_left = vsnode->get_input_port_type(i + 1);
1322
}
1323
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
1324
port_offset++;
1325
1326
valid_left = (i + 2) < vsnode->get_input_port_count();
1327
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1328
if (valid_left) {
1329
port_left = vsnode->get_input_port_type(i + 2);
1330
}
1331
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
1332
port_offset++;
1333
1334
valid_left = (i + 3) < vsnode->get_input_port_count();
1335
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1336
if (valid_left) {
1337
port_left = vsnode->get_input_port_type(i + 3);
1338
}
1339
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
1340
port_offset++;
1341
1342
valid_left = (i + 4) < vsnode->get_input_port_count();
1343
port_left = VisualShaderNode::PORT_TYPE_SCALAR;
1344
if (valid_left) {
1345
port_left = vsnode->get_input_port_type(i + 4);
1346
}
1347
graph_node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[3]);
1348
1349
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_4D;
1350
} break;
1351
default:
1352
break;
1353
}
1354
}
1355
}
1356
}
1357
1358
bool has_relative_parameter_instances = false;
1359
if (vsnode->get_output_port_for_preview() >= 0) {
1360
has_relative_parameter_instances = is_node_has_parameter_instances_relatively(p_type, p_id);
1361
show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview(), !has_relative_parameter_instances);
1362
} else if (!is_reroute) {
1363
offset = memnew(Control);
1364
offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE));
1365
node->add_child(offset);
1366
}
1367
1368
String error = vsnode->get_warning(mode, p_type);
1369
if (has_relative_parameter_instances) {
1370
error += "\n" + TTR("The 2D preview cannot correctly show the result retrieved from instance parameter.");
1371
}
1372
if (!error.is_empty()) {
1373
Label *error_label = memnew(Label);
1374
error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
1375
error_label->add_theme_color_override(SceneStringName(font_color), editor->get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
1376
error_label->set_text(error);
1377
error_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
1378
node->add_child(error_label);
1379
}
1380
1381
if (is_expression) {
1382
CodeEdit *expression_box = memnew(CodeEdit);
1383
Ref<CodeHighlighter> expression_syntax_highlighter;
1384
expression_syntax_highlighter.instantiate();
1385
expression_node->set_ctrl_pressed(expression_box, 0);
1386
expression_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
1387
node->add_child(expression_box);
1388
register_expression_edit(p_id, expression_box);
1389
1390
Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
1391
Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
1392
Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
1393
Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
1394
Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
1395
Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
1396
Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
1397
Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
1398
Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
1399
1400
expression_box->set_syntax_highlighter(expression_syntax_highlighter);
1401
expression_box->add_theme_color_override("background_color", background_color);
1402
1403
for (const String &E : editor->keyword_list) {
1404
if (ShaderLanguage::is_control_flow_keyword(E)) {
1405
expression_syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
1406
} else {
1407
expression_syntax_highlighter->add_keyword_color(E, keyword_color);
1408
}
1409
}
1410
1411
expression_box->begin_bulk_theme_override();
1412
expression_box->add_theme_font_override(SceneStringName(font), editor->get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)));
1413
expression_box->add_theme_font_size_override(SceneStringName(font_size), editor->get_theme_font_size(SNAME("expression_size"), EditorStringName(EditorFonts)));
1414
expression_box->add_theme_color_override(SceneStringName(font_color), text_color);
1415
expression_box->end_bulk_theme_override();
1416
1417
expression_syntax_highlighter->set_number_color(number_color);
1418
expression_syntax_highlighter->set_symbol_color(symbol_color);
1419
expression_syntax_highlighter->set_function_color(function_color);
1420
expression_syntax_highlighter->set_member_variable_color(members_color);
1421
expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
1422
expression_syntax_highlighter->add_color_region("//", "", comment_color, true);
1423
1424
expression_box->clear_comment_delimiters();
1425
expression_box->add_comment_delimiter("/*", "*/", false);
1426
expression_box->add_comment_delimiter("//", "", true);
1427
1428
if (!expression_box->has_auto_brace_completion_open_key("/*")) {
1429
expression_box->add_auto_brace_completion_pair("/*", "*/");
1430
}
1431
1432
expression_box->set_text(expression);
1433
expression_box->set_context_menu_enabled(false);
1434
expression_box->set_draw_line_numbers(true);
1435
1436
expression_box->connect(SceneStringName(focus_exited), callable_mp(editor, &VisualShaderEditor::_expression_focus_out).bind(expression_box, p_id));
1437
}
1438
}
1439
1440
void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id, bool p_just_update) {
1441
if (editor->get_current_shader_type() == p_type && links.has(p_id)) {
1442
GraphEdit *graph_edit = editor->graph;
1443
if (!graph_edit) {
1444
return;
1445
}
1446
1447
graph_edit->remove_child(links[p_id].graph_element);
1448
memdelete(links[p_id].graph_element);
1449
if (!p_just_update) {
1450
links.erase(p_id);
1451
}
1452
}
1453
}
1454
1455
void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1456
GraphEdit *graph = editor->graph;
1457
if (!graph) {
1458
return;
1459
}
1460
1461
if (visual_shader.is_valid() && editor->get_current_shader_type() == p_type) {
1462
// Update reroute nodes since their port type might have changed.
1463
Ref<VisualShaderNodeReroute> reroute_to = visual_shader->get_node(p_type, p_to_node);
1464
Ref<VisualShaderNodeReroute> reroute_from = visual_shader->get_node(p_type, p_from_node);
1465
if (reroute_to.is_valid() || reroute_from.is_valid()) {
1466
update_reroute_nodes();
1467
}
1468
1469
graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
1470
1471
connections.push_back({ p_from_node, p_from_port, p_to_node, p_to_port });
1472
if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) {
1473
links[p_to_node].input_ports[p_to_port].default_input_button->hide();
1474
}
1475
}
1476
}
1477
1478
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
1479
GraphEdit *graph = editor->graph;
1480
if (!graph) {
1481
return;
1482
}
1483
1484
if (visual_shader.is_valid() && editor->get_current_shader_type() == p_type) {
1485
graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
1486
1487
for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
1488
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) {
1489
connections.erase(E);
1490
break;
1491
}
1492
}
1493
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) {
1494
links[p_to_node].input_ports[p_to_port].default_input_button->show();
1495
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));
1496
}
1497
}
1498
}
1499
1500
/////////////////
1501
1502
void VisualShaderEditedProperty::_bind_methods() {
1503
ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualShaderEditedProperty::set_edited_property);
1504
ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualShaderEditedProperty::get_edited_property);
1505
1506
ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property");
1507
}
1508
1509
void VisualShaderEditedProperty::set_edited_property(const Variant &p_variant) {
1510
edited_property = p_variant;
1511
}
1512
1513
Variant VisualShaderEditedProperty::get_edited_property() const {
1514
return edited_property;
1515
}
1516
1517
/////////////////
1518
1519
Vector2 VisualShaderEditor::selection_center;
1520
List<VisualShaderEditor::CopyItem> VisualShaderEditor::copy_items_buffer;
1521
List<VisualShader::Connection> VisualShaderEditor::copy_connections_buffer;
1522
1523
void VisualShaderEditor::edit_shader(const Ref<Shader> &p_shader) {
1524
shader_fully_loaded = false;
1525
bool changed = false;
1526
VisualShader *visual_shader_ptr = Object::cast_to<VisualShader>(p_shader.ptr());
1527
if (visual_shader_ptr) {
1528
if (visual_shader.is_null()) {
1529
changed = true;
1530
} else {
1531
if (visual_shader.ptr() != visual_shader_ptr) {
1532
changed = true;
1533
}
1534
}
1535
visual_shader = p_shader;
1536
graph_plugin->register_shader(visual_shader.ptr());
1537
1538
visual_shader->connect_changed(callable_mp(this, &VisualShaderEditor::_update_preview));
1539
_set_mode(visual_shader->get_mode());
1540
1541
preview_material->set_shader(visual_shader);
1542
_update_nodes();
1543
} else {
1544
if (visual_shader.is_valid()) {
1545
visual_shader->disconnect_changed(callable_mp(this, &VisualShaderEditor::_update_preview));
1546
}
1547
visual_shader.unref();
1548
}
1549
1550
if (visual_shader.is_null()) {
1551
hide();
1552
} else {
1553
if (changed) { // to avoid tree collapse
1554
_update_varying_tree();
1555
_update_options_menu();
1556
_update_preview();
1557
_update_graph();
1558
callable_mp(this, &VisualShaderEditor::_restore_editor_state).call_deferred();
1559
}
1560
}
1561
}
1562
1563
void VisualShaderEditor::use_menu_bar_items(MenuButton *p_file_menu, Button *p_make_floating) {
1564
p_file_menu->set_switch_on_hover(false);
1565
toolbar_hflow->add_child(p_file_menu);
1566
toolbar_hflow->move_child(p_file_menu, 2); // Toggle Files Panel button + separator.
1567
toolbar_hflow->add_child(p_make_floating);
1568
}
1569
1570
void VisualShaderEditor::apply_shaders() {
1571
// Stub. TODO: Implement apply_shaders in visual shaders for parity with text shaders.
1572
}
1573
1574
bool VisualShaderEditor::is_unsaved() const {
1575
// Stub. TODO: Implement is_unsaved in visual shaders for parity with text shaders.
1576
return false;
1577
}
1578
1579
void VisualShaderEditor::save_external_data(const String &p_str) {
1580
ResourceSaver::save(visual_shader, visual_shader->get_path());
1581
}
1582
1583
void VisualShaderEditor::validate_script() {
1584
if (visual_shader.is_valid()) {
1585
_update_nodes();
1586
}
1587
}
1588
1589
void VisualShaderEditor::save_editor_layout() {
1590
const String id_string = _get_cache_id_string();
1591
1592
const String offset_cache_key = _get_cache_key("offset");
1593
const String zoom_cache_key = _get_cache_key("zoom");
1594
vs_editor_cache->set_value(id_string, offset_cache_key, graph->get_scroll_offset() / EDSCALE);
1595
vs_editor_cache->set_value(id_string, zoom_cache_key, graph->get_zoom());
1596
vs_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
1597
}
1598
1599
void VisualShaderEditor::set_current_shader_type(VisualShader::Type p_type) {
1600
current_type = p_type;
1601
1602
const String id_string = _get_cache_id_string();
1603
1604
vs_editor_cache->set_value(id_string, "edited_type", p_type);
1605
vs_editor_cache->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
1606
1607
const String offset_cache_key = _get_cache_key("offset");
1608
const String zoom_cache_key = _get_cache_key("zoom");
1609
const Vector2 saved_scroll_offset = vs_editor_cache->get_value(id_string, offset_cache_key, Vector2());
1610
const real_t saved_zoom = vs_editor_cache->get_value(id_string, zoom_cache_key, 1.0);
1611
1612
graph->set_scroll_offset(saved_scroll_offset);
1613
graph->set_zoom(saved_zoom);
1614
}
1615
1616
VisualShader::Type VisualShaderEditor::get_current_shader_type() const {
1617
return current_type;
1618
}
1619
1620
void VisualShaderEditor::add_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
1621
if (plugins.has(p_plugin)) {
1622
return;
1623
}
1624
plugins.push_back(p_plugin);
1625
}
1626
1627
void VisualShaderEditor::remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin) {
1628
plugins.erase(p_plugin);
1629
}
1630
1631
void VisualShaderEditor::clear_custom_types() {
1632
for (int i = 0; i < add_options.size(); i++) {
1633
if (add_options[i].is_custom) {
1634
add_options.remove_at(i);
1635
i--;
1636
}
1637
}
1638
}
1639
1640
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) {
1641
ERR_FAIL_COND(!p_name.is_valid_ascii_identifier());
1642
ERR_FAIL_COND(p_type.is_empty() && p_script.is_null());
1643
1644
for (int i = 0; i < add_options.size(); i++) {
1645
const AddOption &op = add_options[i];
1646
1647
if (op.is_custom) {
1648
if (!p_type.is_empty()) {
1649
if (op.type == p_type) {
1650
return;
1651
}
1652
} else if (op.script == p_script) {
1653
return;
1654
}
1655
}
1656
}
1657
1658
AddOption ao;
1659
ao.name = p_name;
1660
ao.type = p_type;
1661
ao.script = p_script;
1662
ao.return_type = p_return_icon_type;
1663
ao.description = p_description;
1664
ao.category = p_category;
1665
ao.highend = p_highend;
1666
ao.is_custom = true;
1667
ao.is_native = !p_type.is_empty();
1668
1669
bool begin = false;
1670
String root = p_category.split("/")[0];
1671
1672
for (int i = 0; i < add_options.size(); i++) {
1673
if (add_options[i].is_custom) {
1674
if (add_options[i].category == root) {
1675
if (!begin) {
1676
begin = true;
1677
}
1678
} else {
1679
if (begin) {
1680
add_options.insert(i, ao);
1681
return;
1682
}
1683
}
1684
}
1685
}
1686
add_options.push_back(ao);
1687
}
1688
1689
Dictionary VisualShaderEditor::get_custom_node_data(Ref<VisualShaderNodeCustom> &p_custom_node) {
1690
Dictionary dict;
1691
dict["script"] = p_custom_node->get_script();
1692
dict["name"] = p_custom_node->_get_name();
1693
dict["description"] = p_custom_node->_get_description();
1694
dict["return_icon_type"] = p_custom_node->_get_return_icon_type();
1695
dict["highend"] = p_custom_node->_is_highend();
1696
1697
String category = p_custom_node->_get_category();
1698
category = category.rstrip("/");
1699
category = category.lstrip("/");
1700
category = "Addons/" + category;
1701
if (p_custom_node->has_method("_get_subcategory")) {
1702
String subcategory = (String)p_custom_node->call("_get_subcategory");
1703
if (!subcategory.is_empty()) {
1704
category += "/" + subcategory;
1705
}
1706
}
1707
dict["category"] = category;
1708
1709
return dict;
1710
}
1711
1712
void VisualShaderEditor::_get_current_mode_limits(int &r_begin_type, int &r_end_type) const {
1713
switch (visual_shader->get_mode()) {
1714
case Shader::MODE_CANVAS_ITEM:
1715
case Shader::MODE_SPATIAL: {
1716
r_begin_type = VisualShader::TYPE_VERTEX;
1717
r_end_type = VisualShader::TYPE_START;
1718
} break;
1719
case Shader::MODE_PARTICLES: {
1720
r_begin_type = VisualShader::TYPE_START;
1721
r_end_type = VisualShader::TYPE_SKY;
1722
} break;
1723
case Shader::MODE_SKY: {
1724
r_begin_type = VisualShader::TYPE_SKY;
1725
r_end_type = VisualShader::TYPE_FOG;
1726
} break;
1727
case Shader::MODE_FOG: {
1728
r_begin_type = VisualShader::TYPE_FOG;
1729
r_end_type = VisualShader::TYPE_MAX;
1730
} break;
1731
default: {
1732
} break;
1733
}
1734
}
1735
1736
void VisualShaderEditor::_script_created(const Ref<Script> &p_script) {
1737
if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
1738
return;
1739
}
1740
Ref<VisualShaderNodeCustom> ref;
1741
ref.instantiate();
1742
ref->set_script(p_script);
1743
1744
Dictionary dict = get_custom_node_data(ref);
1745
add_custom_type(dict["name"], String(), dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
1746
1747
_update_options_menu();
1748
}
1749
1750
void VisualShaderEditor::_update_custom_script(const Ref<Script> &p_script) {
1751
if (p_script.is_null() || p_script->get_instance_base_type() != "VisualShaderNodeCustom") {
1752
return;
1753
}
1754
1755
Ref<VisualShaderNodeCustom> ref;
1756
ref.instantiate();
1757
ref->set_script(p_script);
1758
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
1759
for (int i = 0; i < add_options.size(); i++) {
1760
if (add_options[i].is_custom && add_options[i].script == p_script) {
1761
add_options.remove_at(i);
1762
_update_options_menu();
1763
// TODO: Make indication for the existed custom nodes with that script on graph to be disabled.
1764
break;
1765
}
1766
}
1767
return;
1768
}
1769
Dictionary dict = get_custom_node_data(ref);
1770
1771
bool found_type = false;
1772
bool need_rebuild = false;
1773
1774
for (int i = custom_node_option_idx; i < add_options.size(); i++) {
1775
if (add_options[i].script == p_script) {
1776
found_type = true;
1777
1778
add_options.write[i].name = dict["name"];
1779
add_options.write[i].return_type = dict["return_icon_type"];
1780
add_options.write[i].description = dict["description"];
1781
add_options.write[i].category = dict["category"];
1782
add_options.write[i].highend = dict["highend"];
1783
1784
int begin_type = 0;
1785
int end_type = 0;
1786
_get_current_mode_limits(begin_type, end_type);
1787
1788
for (int t = begin_type; t < end_type; t++) {
1789
VisualShader::Type type = (VisualShader::Type)t;
1790
Vector<int> nodes = visual_shader->get_node_list(type);
1791
1792
List<VisualShader::Connection> node_connections;
1793
visual_shader->get_node_connections(type, &node_connections);
1794
1795
List<VisualShader::Connection> custom_node_input_connections;
1796
List<VisualShader::Connection> custom_node_output_connections;
1797
1798
for (const VisualShader::Connection &E : node_connections) {
1799
int from = E.from_node;
1800
int from_port = E.from_port;
1801
int to = E.to_node;
1802
int to_port = E.to_port;
1803
1804
if (graph_plugin->get_node_script(from) == p_script) {
1805
custom_node_output_connections.push_back({ from, from_port, to, to_port });
1806
} else if (graph_plugin->get_node_script(to) == p_script) {
1807
custom_node_input_connections.push_back({ from, from_port, to, to_port });
1808
}
1809
}
1810
1811
for (int node_id : nodes) {
1812
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
1813
if (vsnode.is_null()) {
1814
continue;
1815
}
1816
Ref<VisualShaderNodeCustom> custom_node = vsnode;
1817
if (custom_node.is_null() || custom_node->get_script() != p_script) {
1818
continue;
1819
}
1820
need_rebuild = true;
1821
1822
// Removes invalid connections.
1823
{
1824
int prev_input_port_count = custom_node->get_input_port_count();
1825
int prev_output_port_count = custom_node->get_output_port_count();
1826
1827
custom_node->update_ports();
1828
1829
int input_port_count = custom_node->get_input_port_count();
1830
int output_port_count = custom_node->get_output_port_count();
1831
1832
if (output_port_count != prev_output_port_count) {
1833
for (const VisualShader::Connection &E : custom_node_output_connections) {
1834
int from = E.from_node;
1835
int from_idx = E.from_port;
1836
int to = E.to_node;
1837
int to_idx = E.to_port;
1838
1839
if (from_idx >= output_port_count) {
1840
visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
1841
graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
1842
}
1843
}
1844
}
1845
if (input_port_count != prev_input_port_count) {
1846
for (const VisualShader::Connection &E : custom_node_input_connections) {
1847
int from = E.from_node;
1848
int from_idx = E.from_port;
1849
int to = E.to_node;
1850
int to_idx = E.to_port;
1851
1852
if (to_idx >= input_port_count) {
1853
visual_shader->disconnect_nodes(type, from, from_idx, to, to_idx);
1854
graph_plugin->disconnect_nodes(type, from, from_idx, to, to_idx);
1855
}
1856
}
1857
}
1858
}
1859
1860
graph_plugin->update_node(type, node_id);
1861
}
1862
}
1863
break;
1864
}
1865
}
1866
1867
if (!found_type) {
1868
add_custom_type(dict["name"], String(), dict["script"], dict["description"], dict["return_icon_type"], dict["category"], dict["highend"]);
1869
}
1870
1871
// To prevent updating options multiple times when multiple scripts are saved.
1872
if (!_block_update_options_menu) {
1873
_block_update_options_menu = true;
1874
1875
callable_mp(this, &VisualShaderEditor::_update_options_menu_deferred);
1876
}
1877
1878
// To prevent rebuilding the shader multiple times when multiple scripts are saved.
1879
if (need_rebuild && !_block_rebuild_shader) {
1880
_block_rebuild_shader = true;
1881
1882
callable_mp(this, &VisualShaderEditor::_rebuild_shader_deferred);
1883
}
1884
}
1885
1886
void VisualShaderEditor::_resource_saved(const Ref<Resource> &p_resource) {
1887
_update_custom_script(Ref<Script>(p_resource.ptr()));
1888
}
1889
1890
void VisualShaderEditor::_resources_removed() {
1891
bool has_any_instance = false;
1892
1893
for (const Ref<Script> &scr : custom_scripts_to_delete) {
1894
for (int i = custom_node_option_idx; i < add_options.size(); i++) {
1895
if (add_options[i].script == scr) {
1896
add_options.remove_at(i);
1897
1898
// Removes all node instances using that script from the graph.
1899
{
1900
int begin_type = 0;
1901
int end_type = 0;
1902
_get_current_mode_limits(begin_type, end_type);
1903
1904
for (int t = begin_type; t < end_type; t++) {
1905
VisualShader::Type type = (VisualShader::Type)t;
1906
1907
List<VisualShader::Connection> node_connections;
1908
visual_shader->get_node_connections(type, &node_connections);
1909
1910
for (const VisualShader::Connection &E : node_connections) {
1911
int from = E.from_node;
1912
int from_port = E.from_port;
1913
int to = E.to_node;
1914
int to_port = E.to_port;
1915
1916
if (graph_plugin->get_node_script(from) == scr || graph_plugin->get_node_script(to) == scr) {
1917
visual_shader->disconnect_nodes(type, from, from_port, to, to_port);
1918
graph_plugin->disconnect_nodes(type, from, from_port, to, to_port);
1919
}
1920
}
1921
1922
Vector<int> nodes = visual_shader->get_node_list(type);
1923
for (int node_id : nodes) {
1924
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
1925
if (vsnode.is_null()) {
1926
continue;
1927
}
1928
Ref<VisualShaderNodeCustom> custom_node = vsnode;
1929
if (custom_node.is_null() || custom_node->get_script() != scr) {
1930
continue;
1931
}
1932
visual_shader->remove_node(type, node_id);
1933
graph_plugin->remove_node(type, node_id, false);
1934
1935
has_any_instance = true;
1936
}
1937
}
1938
}
1939
1940
break;
1941
}
1942
}
1943
}
1944
if (has_any_instance) {
1945
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).
1946
ResourceSaver::save(visual_shader, visual_shader->get_path());
1947
}
1948
_update_options_menu();
1949
1950
custom_scripts_to_delete.clear();
1951
pending_custom_scripts_to_delete = false;
1952
}
1953
1954
void VisualShaderEditor::_resource_removed(const Ref<Resource> &p_resource) {
1955
Ref<Script> scr = Ref<Script>(p_resource.ptr());
1956
if (scr.is_null() || scr->get_instance_base_type() != "VisualShaderNodeCustom") {
1957
return;
1958
}
1959
1960
custom_scripts_to_delete.push_back(scr);
1961
1962
if (!pending_custom_scripts_to_delete) {
1963
pending_custom_scripts_to_delete = true;
1964
callable_mp(this, &VisualShaderEditor::_resources_removed).call_deferred();
1965
}
1966
}
1967
1968
void VisualShaderEditor::_update_options_menu_deferred() {
1969
_update_options_menu();
1970
1971
_block_update_options_menu = false;
1972
}
1973
1974
void VisualShaderEditor::_rebuild_shader_deferred() {
1975
if (visual_shader.is_valid()) {
1976
visual_shader->rebuild();
1977
}
1978
1979
_block_rebuild_shader = false;
1980
}
1981
1982
bool VisualShaderEditor::_is_available(int p_mode) {
1983
int current_mode = edit_type->get_selected();
1984
1985
if (p_mode != -1) {
1986
switch (current_mode) {
1987
case 0: // Vertex / Emit
1988
current_mode = 1;
1989
break;
1990
case 1: // Fragment / Process
1991
current_mode = 2;
1992
break;
1993
case 2: // Light / Collide
1994
current_mode = 4;
1995
break;
1996
default:
1997
break;
1998
}
1999
}
2000
2001
return (p_mode == -1 || (p_mode & current_mode) != 0);
2002
}
2003
2004
bool VisualShaderEditor::_update_preview_parameter_tree() {
2005
bool found = false;
2006
bool use_filter = !param_filter_name.is_empty();
2007
2008
parameters->clear();
2009
TreeItem *root = parameters->create_item();
2010
2011
for (const KeyValue<String, PropertyInfo> &prop : parameter_props) {
2012
String param_name = prop.value.name;
2013
if (use_filter && !param_name.containsn(param_filter_name)) {
2014
continue;
2015
}
2016
2017
TreeItem *item = parameters->create_item(root);
2018
item->set_text(0, param_name);
2019
item->set_meta("id", param_name);
2020
2021
if (param_name == selected_param_id) {
2022
parameters->set_selected(item);
2023
found = true;
2024
}
2025
2026
if (prop.value.type == Variant::OBJECT) {
2027
item->set_icon(0, get_editor_theme_icon(SNAME("ImageTexture")));
2028
} else {
2029
item->set_icon(0, get_editor_theme_icon(Variant::get_type_name(prop.value.type)));
2030
}
2031
}
2032
2033
return found;
2034
}
2035
2036
void VisualShaderEditor::_preview_tools_menu_option(int p_idx) {
2037
ShaderMaterial *src_mat = nullptr;
2038
2039
if (p_idx == COPY_PARAMS_FROM_MATERIAL || p_idx == PASTE_PARAMS_TO_MATERIAL) {
2040
for (int i = EditorNode::get_singleton()->get_editor_selection_history()->get_path_size() - 1; i >= 0; i--) {
2041
Object *object = ObjectDB::get_instance(EditorNode::get_singleton()->get_editor_selection_history()->get_path_object(i));
2042
ShaderMaterial *src_mat2;
2043
if (!object) {
2044
continue;
2045
}
2046
if (object->has_method("get_material_override")) { // Trying to get material from MeshInstance.
2047
src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material_override"));
2048
} else if (object->has_method("get_material")) { // From CanvasItem/Node2D.
2049
src_mat2 = Object::cast_to<ShaderMaterial>(object->call("get_material"));
2050
} else {
2051
src_mat2 = Object::cast_to<ShaderMaterial>(object);
2052
}
2053
2054
if (src_mat2 && src_mat2->get_shader().is_valid() && src_mat2->get_shader() == visual_shader) {
2055
src_mat = src_mat2;
2056
break;
2057
}
2058
}
2059
}
2060
2061
switch (p_idx) {
2062
case COPY_PARAMS_FROM_MATERIAL:
2063
if (src_mat) {
2064
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2065
undo_redo->create_action(TTR("Copy Preview Shader Parameters From Material"));
2066
2067
List<PropertyInfo> params;
2068
preview_material->get_shader()->get_shader_uniform_list(&params);
2069
for (const PropertyInfo &E : params) {
2070
undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, src_mat->get_shader_parameter(E.name));
2071
undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", E.name, preview_material->get_shader_parameter(E.name));
2072
}
2073
2074
undo_redo->commit_action();
2075
}
2076
break;
2077
case PASTE_PARAMS_TO_MATERIAL:
2078
if (src_mat) {
2079
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2080
undo_redo->create_action(TTR("Paste Preview Shader Parameters To Material"));
2081
2082
List<PropertyInfo> params;
2083
preview_material->get_shader()->get_shader_uniform_list(&params);
2084
for (const PropertyInfo &E : params) {
2085
undo_redo->add_do_method(src_mat, "set_shader_parameter", E.name, preview_material->get_shader_parameter(E.name));
2086
undo_redo->add_undo_method(src_mat, "set_shader_parameter", E.name, src_mat->get_shader_parameter(E.name));
2087
}
2088
2089
undo_redo->commit_action();
2090
}
2091
break;
2092
default:
2093
break;
2094
}
2095
}
2096
2097
void VisualShaderEditor::_clear_preview_param() {
2098
selected_param_id = "";
2099
current_prop = nullptr;
2100
2101
if (param_vbox2->get_child_count() > 0) {
2102
param_vbox2->remove_child(param_vbox2->get_child(0));
2103
}
2104
2105
param_vbox->hide();
2106
}
2107
2108
void VisualShaderEditor::_update_preview_parameter_list() {
2109
material_editor->edit(preview_material.ptr(), env);
2110
2111
List<PropertyInfo> properties;
2112
RenderingServer::get_singleton()->get_shader_parameter_list(visual_shader->get_rid(), &properties);
2113
2114
HashSet<String> params_to_remove;
2115
for (const KeyValue<String, PropertyInfo> &E : parameter_props) {
2116
params_to_remove.insert(E.key);
2117
}
2118
parameter_props.clear();
2119
2120
for (const PropertyInfo &prop : properties) {
2121
String param_name = prop.name;
2122
2123
if (visual_shader->_has_preview_shader_parameter(param_name)) {
2124
preview_material->set_shader_parameter(param_name, visual_shader->_get_preview_shader_parameter(param_name));
2125
} else {
2126
preview_material->set_shader_parameter(param_name, RenderingServer::get_singleton()->shader_get_parameter_default(visual_shader->get_rid(), param_name));
2127
}
2128
2129
parameter_props.insert(param_name, prop);
2130
params_to_remove.erase(param_name);
2131
2132
if (param_name == selected_param_id) {
2133
current_prop->update_property();
2134
current_prop->update_editor_property_status();
2135
current_prop->update_cache();
2136
}
2137
}
2138
2139
_update_preview_parameter_tree();
2140
2141
// Removes invalid parameters.
2142
for (const String &param_name : params_to_remove) {
2143
preview_material->set_shader_parameter(param_name, Variant());
2144
2145
if (visual_shader->_has_preview_shader_parameter(param_name)) {
2146
visual_shader->_set_preview_shader_parameter(param_name, Variant());
2147
}
2148
2149
if (param_name == selected_param_id) {
2150
_clear_preview_param();
2151
}
2152
}
2153
}
2154
2155
void VisualShaderEditor::_update_nodes() {
2156
clear_custom_types();
2157
Dictionary added;
2158
2159
// Add GDScript classes.
2160
{
2161
List<StringName> class_list;
2162
ScriptServer::get_global_class_list(&class_list);
2163
2164
for (const StringName &E : class_list) {
2165
if (ScriptServer::get_global_class_native_base(E) == "VisualShaderNodeCustom") {
2166
String script_path = ScriptServer::get_global_class_path(E);
2167
Ref<Resource> res = ResourceLoader::load(script_path);
2168
ERR_CONTINUE(res.is_null());
2169
ERR_CONTINUE(!res->is_class("Script"));
2170
Ref<Script> scr = Ref<Script>(res);
2171
2172
Ref<VisualShaderNodeCustom> ref;
2173
ref.instantiate();
2174
ref->set_script(scr);
2175
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2176
continue;
2177
}
2178
Dictionary dict = get_custom_node_data(ref);
2179
dict["type"] = String();
2180
2181
String key;
2182
key = String(dict["category"]) + "/" + String(dict["name"]);
2183
2184
added[key] = dict;
2185
}
2186
}
2187
}
2188
2189
// Add GDExtension classes.
2190
{
2191
List<StringName> class_list;
2192
ClassDB::get_class_list(&class_list);
2193
2194
for (const StringName &E : class_list) {
2195
if (ClassDB::get_parent_class(E) == "VisualShaderNodeCustom") {
2196
Object *instance = ClassDB::instantiate(E);
2197
Ref<VisualShaderNodeCustom> ref = Object::cast_to<VisualShaderNodeCustom>(instance);
2198
ERR_CONTINUE(ref.is_null());
2199
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2200
continue;
2201
}
2202
Dictionary dict = get_custom_node_data(ref);
2203
dict["type"] = E;
2204
dict["script"] = Ref<Script>();
2205
2206
String key;
2207
key = String(dict["category"]) + "/" + String(dict["name"]);
2208
2209
added[key] = dict;
2210
}
2211
}
2212
}
2213
2214
// Disables not-supported copied items.
2215
{
2216
for (CopyItem &item : copy_items_buffer) {
2217
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(item.node.ptr());
2218
2219
if (custom.is_valid()) {
2220
if (!custom->is_available(visual_shader->get_mode(), get_current_shader_type())) {
2221
item.disabled = true;
2222
} else {
2223
item.disabled = false;
2224
}
2225
} else {
2226
for (int i = 0; i < add_options.size(); i++) {
2227
if (add_options[i].type == item.node->get_class_name()) {
2228
if ((add_options[i].func != visual_shader->get_mode() && add_options[i].func != -1) || !_is_available(add_options[i].mode)) {
2229
item.disabled = true;
2230
} else {
2231
item.disabled = false;
2232
}
2233
break;
2234
}
2235
}
2236
}
2237
}
2238
}
2239
2240
LocalVector<Variant> keys = added.get_key_list();
2241
keys.sort_custom<StringLikeVariantOrder>();
2242
2243
for (const Variant &key : keys) {
2244
const Dictionary &value = (Dictionary)added[key];
2245
2246
add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]);
2247
}
2248
2249
_update_options_menu();
2250
}
2251
2252
String VisualShaderEditor::_get_description(int p_idx) {
2253
return add_options[p_idx].description;
2254
}
2255
2256
void VisualShaderEditor::_update_options_menu() {
2257
node_desc->set_text("");
2258
highend_label->set_visible(false);
2259
members_dialog->get_ok_button()->set_disabled(true);
2260
2261
members->clear();
2262
TreeItem *root = members->create_item();
2263
2264
String filter = node_filter->get_text().strip_edges();
2265
bool use_filter = !filter.is_empty();
2266
2267
bool is_first_item = true;
2268
2269
Color unsupported_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
2270
Color supported_color = get_theme_color(SNAME("warning_color"), EditorStringName(Editor));
2271
2272
static bool low_driver = GLOBAL_GET("rendering/renderer/rendering_method") == "gl_compatibility";
2273
2274
HashMap<String, TreeItem *> folders;
2275
2276
int current_func = -1;
2277
2278
if (visual_shader.is_valid()) {
2279
current_func = visual_shader->get_mode();
2280
}
2281
2282
Vector<AddOption> custom_options;
2283
Vector<AddOption> embedded_options;
2284
2285
static Vector<String> type_filter_exceptions;
2286
if (type_filter_exceptions.is_empty()) {
2287
type_filter_exceptions.append("VisualShaderNodeExpression");
2288
type_filter_exceptions.append("VisualShaderNodeReroute");
2289
}
2290
2291
for (int i = 0; i < add_options.size(); i++) {
2292
if (!use_filter || add_options[i].name.containsn(filter)) {
2293
// port type filtering
2294
if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX || members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2295
Ref<VisualShaderNode> vsn;
2296
int check_result = 0;
2297
2298
if (!add_options[i].is_custom) {
2299
vsn = Ref<VisualShaderNode>(Object::cast_to<VisualShaderNode>(ClassDB::instantiate(add_options[i].type)));
2300
if (vsn.is_null()) {
2301
continue;
2302
}
2303
2304
if (type_filter_exceptions.has(add_options[i].type)) {
2305
check_result = 1;
2306
}
2307
2308
Ref<VisualShaderNodeInput> input = Object::cast_to<VisualShaderNodeInput>(vsn.ptr());
2309
if (input.is_valid()) {
2310
input->set_shader_mode(visual_shader->get_mode());
2311
input->set_shader_type(get_current_shader_type());
2312
if (!add_options[i].ops.is_empty() && add_options[i].ops[0].is_string()) {
2313
input->set_input_name((String)add_options[i].ops[0]);
2314
}
2315
}
2316
2317
Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(vsn.ptr());
2318
if (expression.is_valid()) {
2319
if (members_input_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
2320
check_result = -1; // expressions creates a port with required type automatically (except for sampler output)
2321
}
2322
}
2323
2324
Ref<VisualShaderNodeParameterRef> parameter_ref = Object::cast_to<VisualShaderNodeParameterRef>(vsn.ptr());
2325
if (parameter_ref.is_valid() && parameter_ref->is_shader_valid()) {
2326
check_result = -1;
2327
2328
if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2329
for (int j = 0; j < parameter_ref->get_parameters_count(); j++) {
2330
if (visual_shader->is_port_types_compatible(parameter_ref->get_port_type_by_index(j), members_input_port_type)) {
2331
check_result = 1;
2332
break;
2333
}
2334
}
2335
}
2336
}
2337
} else {
2338
check_result = 1;
2339
}
2340
2341
if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2342
if (check_result == 0) {
2343
for (int j = 0; j < vsn->get_input_port_count(); j++) {
2344
if (visual_shader->is_port_types_compatible(vsn->get_input_port_type(j), members_output_port_type)) {
2345
check_result = 1;
2346
break;
2347
}
2348
}
2349
}
2350
2351
if (check_result != 1) {
2352
continue;
2353
}
2354
}
2355
if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) {
2356
if (check_result == 0) {
2357
for (int j = 0; j < vsn->get_output_port_count(); j++) {
2358
if (visual_shader->is_port_types_compatible(vsn->get_output_port_type(j), members_input_port_type)) {
2359
check_result = 1;
2360
break;
2361
}
2362
}
2363
}
2364
2365
if (check_result != 1) {
2366
continue;
2367
}
2368
}
2369
}
2370
if ((add_options[i].func != current_func && add_options[i].func != -1) || !_is_available(add_options[i].mode)) {
2371
continue;
2372
}
2373
add_options[i].temp_idx = i; // save valid id
2374
if (add_options[i].is_custom) {
2375
custom_options.push_back(add_options[i]);
2376
} else {
2377
embedded_options.push_back(add_options[i]);
2378
}
2379
}
2380
}
2381
Vector<AddOption> options;
2382
SortArray<AddOption, _OptionComparator> sorter;
2383
sorter.sort(custom_options.ptrw(), custom_options.size());
2384
2385
options.append_array(custom_options);
2386
options.append_array(embedded_options);
2387
2388
for (int i = 0; i < options.size(); i++) {
2389
String path = options[i].category;
2390
Vector<String> subfolders = path.split("/");
2391
TreeItem *category = nullptr;
2392
2393
if (!folders.has(path)) {
2394
category = root;
2395
String path_temp = "";
2396
for (int j = 0; j < subfolders.size(); j++) {
2397
path_temp += subfolders[j];
2398
if (!folders.has(path_temp)) {
2399
category = members->create_item(category);
2400
category->set_selectable(0, false);
2401
category->set_collapsed(!use_filter);
2402
category->set_text(0, subfolders[j]);
2403
folders.insert(path_temp, category);
2404
} else {
2405
category = folders[path_temp];
2406
}
2407
}
2408
} else {
2409
category = folders[path];
2410
}
2411
2412
TreeItem *item = members->create_item(category);
2413
if (options[i].highend && low_driver) {
2414
item->set_custom_color(0, unsupported_color);
2415
} else if (options[i].highend) {
2416
item->set_custom_color(0, supported_color);
2417
}
2418
item->set_text(0, options[i].name);
2419
if (is_first_item && use_filter) {
2420
item->select(0);
2421
node_desc->set_text(options[i].description);
2422
is_first_item = false;
2423
2424
members_dialog->get_ok_button()->set_disabled(false);
2425
}
2426
switch (options[i].return_type) {
2427
case VisualShaderNode::PORT_TYPE_SCALAR:
2428
item->set_icon(0, get_editor_theme_icon(SNAME("float")));
2429
break;
2430
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
2431
item->set_icon(0, get_editor_theme_icon(SNAME("int")));
2432
break;
2433
case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
2434
item->set_icon(0, get_editor_theme_icon(SNAME("uint")));
2435
break;
2436
case VisualShaderNode::PORT_TYPE_VECTOR_2D:
2437
item->set_icon(0, get_editor_theme_icon(SNAME("Vector2")));
2438
break;
2439
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
2440
item->set_icon(0, get_editor_theme_icon(SNAME("Vector3")));
2441
break;
2442
case VisualShaderNode::PORT_TYPE_VECTOR_4D:
2443
item->set_icon(0, get_editor_theme_icon(SNAME("Vector4")));
2444
break;
2445
case VisualShaderNode::PORT_TYPE_BOOLEAN:
2446
item->set_icon(0, get_editor_theme_icon(SNAME("bool")));
2447
break;
2448
case VisualShaderNode::PORT_TYPE_TRANSFORM:
2449
item->set_icon(0, get_editor_theme_icon(SNAME("Transform3D")));
2450
break;
2451
case VisualShaderNode::PORT_TYPE_SAMPLER:
2452
item->set_icon(0, get_editor_theme_icon(SNAME("ImageTexture")));
2453
break;
2454
default:
2455
break;
2456
}
2457
item->set_meta("id", options[i].temp_idx);
2458
}
2459
}
2460
2461
void VisualShaderEditor::_set_mode(int p_which) {
2462
if (p_which == VisualShader::MODE_SKY) {
2463
edit_type_standard->set_visible(false);
2464
edit_type_particles->set_visible(false);
2465
edit_type_sky->set_visible(true);
2466
edit_type_fog->set_visible(false);
2467
edit_type = edit_type_sky;
2468
custom_mode_box->set_visible(false);
2469
varying_button->hide();
2470
mode = MODE_FLAGS_SKY;
2471
} else if (p_which == VisualShader::MODE_FOG) {
2472
edit_type_standard->set_visible(false);
2473
edit_type_particles->set_visible(false);
2474
edit_type_sky->set_visible(false);
2475
edit_type_fog->set_visible(true);
2476
edit_type = edit_type_fog;
2477
custom_mode_box->set_visible(false);
2478
varying_button->hide();
2479
mode = MODE_FLAGS_FOG;
2480
} else if (p_which == VisualShader::MODE_PARTICLES) {
2481
edit_type_standard->set_visible(false);
2482
edit_type_particles->set_visible(true);
2483
edit_type_sky->set_visible(false);
2484
edit_type_fog->set_visible(false);
2485
edit_type = edit_type_particles;
2486
if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
2487
custom_mode_box->set_visible(false);
2488
} else {
2489
custom_mode_box->set_visible(true);
2490
}
2491
varying_button->hide();
2492
mode = MODE_FLAGS_PARTICLES;
2493
} else {
2494
edit_type_particles->set_visible(false);
2495
edit_type_standard->set_visible(true);
2496
edit_type_sky->set_visible(false);
2497
edit_type_fog->set_visible(false);
2498
edit_type = edit_type_standard;
2499
custom_mode_box->set_visible(false);
2500
varying_button->show();
2501
mode = MODE_FLAGS_SPATIAL_CANVASITEM;
2502
}
2503
2504
const String id_string = _get_cache_id_string();
2505
2506
int default_type = VisualShader::TYPE_VERTEX;
2507
int upper_type = VisualShader::TYPE_START;
2508
if (mode & MODE_FLAGS_PARTICLES) {
2509
default_type = VisualShader::TYPE_START;
2510
upper_type = VisualShader::TYPE_SKY;
2511
} else if (mode & MODE_FLAGS_SKY) {
2512
default_type = VisualShader::TYPE_SKY;
2513
upper_type = VisualShader::TYPE_FOG;
2514
} else if (mode & MODE_FLAGS_FOG) {
2515
default_type = VisualShader::TYPE_FOG;
2516
upper_type = VisualShader::TYPE_MAX;
2517
}
2518
2519
int saved_type = vs_editor_cache->get_value(id_string, "edited_type", default_type);
2520
if (saved_type >= upper_type || saved_type < default_type) {
2521
saved_type = default_type;
2522
}
2523
2524
if (mode & MODE_FLAGS_PARTICLES && saved_type - default_type >= 3) {
2525
edit_type->select(saved_type - default_type - 3);
2526
custom_mode_box->set_pressed(true);
2527
} else {
2528
edit_type->select(saved_type - default_type);
2529
}
2530
set_current_shader_type((VisualShader::Type)saved_type);
2531
}
2532
2533
Size2 VisualShaderEditor::get_minimum_size() const {
2534
return Size2(10, 200);
2535
}
2536
2537
void VisualShaderEditor::update_toggle_files_button() {
2538
ERR_FAIL_NULL(toggle_files_list);
2539
bool forward = toggle_files_list->is_visible() == is_layout_rtl();
2540
toggle_files_button->set_button_icon(get_editor_theme_icon(forward ? SNAME("Forward") : SNAME("Back")));
2541
toggle_files_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Files Panel"), ED_GET_SHORTCUT("script_editor/toggle_files_panel")->get_as_text()));
2542
}
2543
2544
void VisualShaderEditor::_draw_color_over_button(Object *p_obj, Color p_color) {
2545
Button *button = Object::cast_to<Button>(p_obj);
2546
if (!button) {
2547
return;
2548
}
2549
2550
Ref<StyleBox> normal = get_theme_stylebox(CoreStringName(normal), SNAME("Button"));
2551
button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color);
2552
}
2553
2554
void VisualShaderEditor::_update_parameters(bool p_update_refs) {
2555
VisualShaderNodeParameterRef::clear_parameters(visual_shader->get_rid());
2556
2557
for (int t = 0; t < VisualShader::TYPE_MAX; t++) {
2558
Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t);
2559
for (int i = 0; i < tnodes.size(); i++) {
2560
Ref<VisualShaderNode> vsnode = visual_shader->get_node((VisualShader::Type)t, tnodes[i]);
2561
Ref<VisualShaderNodeParameter> parameter = vsnode;
2562
2563
if (parameter.is_valid()) {
2564
Ref<VisualShaderNodeFloatParameter> float_parameter = vsnode;
2565
Ref<VisualShaderNodeIntParameter> int_parameter = vsnode;
2566
Ref<VisualShaderNodeUIntParameter> uint_parameter = vsnode;
2567
Ref<VisualShaderNodeVec2Parameter> vec2_parameter = vsnode;
2568
Ref<VisualShaderNodeVec3Parameter> vec3_parameter = vsnode;
2569
Ref<VisualShaderNodeVec4Parameter> vec4_parameter = vsnode;
2570
Ref<VisualShaderNodeColorParameter> color_parameter = vsnode;
2571
Ref<VisualShaderNodeBooleanParameter> boolean_parameter = vsnode;
2572
Ref<VisualShaderNodeTransformParameter> transform_parameter = vsnode;
2573
2574
VisualShaderNodeParameterRef::ParameterType parameter_type;
2575
if (float_parameter.is_valid()) {
2576
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_FLOAT;
2577
} else if (int_parameter.is_valid()) {
2578
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_INT;
2579
} else if (uint_parameter.is_valid()) {
2580
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_UINT;
2581
} else if (boolean_parameter.is_valid()) {
2582
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_BOOLEAN;
2583
} else if (vec2_parameter.is_valid()) {
2584
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR2;
2585
} else if (vec3_parameter.is_valid()) {
2586
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR3;
2587
} else if (vec4_parameter.is_valid()) {
2588
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_VECTOR4;
2589
} else if (transform_parameter.is_valid()) {
2590
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_TRANSFORM;
2591
} else if (color_parameter.is_valid()) {
2592
parameter_type = VisualShaderNodeParameterRef::PARAMETER_TYPE_COLOR;
2593
} else {
2594
parameter_type = VisualShaderNodeParameterRef::UNIFORM_TYPE_SAMPLER;
2595
}
2596
VisualShaderNodeParameterRef::add_parameter(visual_shader->get_rid(), parameter->get_parameter_name(), parameter_type);
2597
}
2598
}
2599
}
2600
if (p_update_refs) {
2601
graph_plugin->update_parameter_refs();
2602
}
2603
}
2604
2605
void VisualShaderEditor::_update_parameter_refs(HashSet<String> &p_deleted_names) {
2606
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2607
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
2608
VisualShader::Type type = VisualShader::Type(i);
2609
2610
Vector<int> nodes = visual_shader->get_node_list(type);
2611
for (int j = 0; j < nodes.size(); j++) {
2612
if (j > 0) {
2613
Ref<VisualShaderNodeParameterRef> ref = visual_shader->get_node(type, nodes[j]);
2614
if (ref.is_valid()) {
2615
if (p_deleted_names.has(ref->get_parameter_name())) {
2616
undo_redo->add_do_method(ref.ptr(), "set_parameter_name", "[None]");
2617
undo_redo->add_undo_method(ref.ptr(), "set_parameter_name", ref->get_parameter_name());
2618
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]);
2619
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", VisualShader::Type(i), nodes[j]);
2620
}
2621
}
2622
}
2623
}
2624
}
2625
}
2626
2627
void VisualShaderEditor::_update_graph() {
2628
if (visual_shader.is_null()) {
2629
return;
2630
}
2631
2632
VisualShader::Type type = get_current_shader_type();
2633
2634
graph->clear_connections();
2635
// Remove all nodes.
2636
for (int i = 0; i < graph->get_child_count(); i++) {
2637
if (Object::cast_to<GraphElement>(graph->get_child(i))) {
2638
Node *node = graph->get_child(i);
2639
graph->remove_child(node);
2640
memdelete(node);
2641
i--;
2642
}
2643
}
2644
2645
List<VisualShader::Connection> node_connections;
2646
visual_shader->get_node_connections(type, &node_connections);
2647
graph_plugin->set_connections(node_connections);
2648
2649
Vector<int> nodes = visual_shader->get_node_list(type);
2650
2651
_update_parameters(false);
2652
_update_varyings();
2653
2654
graph_plugin->clear_links();
2655
graph_plugin->update_theme();
2656
2657
for (int n_i = 0; n_i < nodes.size(); n_i++) {
2658
// Update frame related stuff later since we need to have all nodes in the graph.
2659
graph_plugin->add_node(type, nodes[n_i], false, false);
2660
}
2661
2662
for (const VisualShader::Connection &E : node_connections) {
2663
int from = E.from_node;
2664
int from_idx = E.from_port;
2665
int to = E.to_node;
2666
int to_idx = E.to_port;
2667
2668
graph->connect_node(itos(from), from_idx, itos(to), to_idx);
2669
}
2670
2671
// Attach nodes to frames.
2672
for (int node_id : nodes) {
2673
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
2674
ERR_CONTINUE_MSG(vsnode.is_null(), "Node is null.");
2675
2676
if (vsnode->get_frame() != -1) {
2677
int frame_name = vsnode->get_frame();
2678
graph->attach_graph_element_to_frame(itos(node_id), itos(frame_name));
2679
}
2680
}
2681
2682
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
2683
graph->set_minimap_opacity(graph_minimap_opacity);
2684
float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature");
2685
graph->set_connection_lines_curvature(graph_lines_curvature);
2686
}
2687
2688
void VisualShaderEditor::_restore_editor_state() {
2689
const String id_string = _get_cache_id_string();
2690
2691
const String offset_cache_key = _get_cache_key("offset");
2692
const String zoom_cache_key = _get_cache_key("zoom");
2693
const Vector2 saved_scroll_offset = vs_editor_cache->get_value(id_string, offset_cache_key, Vector2());
2694
const real_t saved_zoom = vs_editor_cache->get_value(id_string, zoom_cache_key, 1.0);
2695
2696
// Setting the scroll offset needs to be further deferred because it requires min/max scroll offset to be final (as it gets clamped).
2697
callable_mp(graph, &GraphEdit::set_zoom).call_deferred(saved_zoom);
2698
callable_mp(graph, &GraphEdit::set_scroll_offset).call_deferred(saved_scroll_offset);
2699
2700
shader_fully_loaded = true;
2701
}
2702
2703
String VisualShaderEditor::_get_cache_id_string() const {
2704
String id_string = visual_shader->get_path();
2705
const ResourceUID::ID uid = EditorFileSystem::get_singleton()->get_file_uid(id_string);
2706
if (uid != ResourceUID::INVALID_ID) {
2707
id_string = ResourceUID::get_singleton()->id_to_text(uid);
2708
}
2709
return id_string;
2710
}
2711
2712
String VisualShaderEditor::_get_cache_key(const String &p_prop_name) const {
2713
const int type = get_current_shader_type();
2714
return "type" + itos(type) + ":" + p_prop_name;
2715
}
2716
2717
void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type, const String &p_name) {
2718
VisualShader::Type type = get_current_shader_type();
2719
Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
2720
if (node.is_null()) {
2721
return;
2722
}
2723
2724
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2725
undo_redo->create_action(TTR("Add Input Port"));
2726
undo_redo->add_do_method(node.ptr(), "add_input_port", p_port, p_port_type, p_name);
2727
undo_redo->add_undo_method(node.ptr(), "remove_input_port", p_port);
2728
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2729
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2730
undo_redo->commit_action();
2731
}
2732
2733
void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_type, const String &p_name) {
2734
VisualShader::Type type = get_current_shader_type();
2735
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2736
if (node.is_null()) {
2737
return;
2738
}
2739
2740
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2741
undo_redo->create_action(TTR("Add Output Port"));
2742
undo_redo->add_do_method(node.ptr(), "add_output_port", p_port, p_port_type, p_name);
2743
undo_redo->add_undo_method(node.ptr(), "remove_output_port", p_port);
2744
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2745
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2746
undo_redo->commit_action();
2747
}
2748
2749
void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_port) {
2750
VisualShader::Type type = get_current_shader_type();
2751
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2752
if (node.is_null()) {
2753
return;
2754
}
2755
2756
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2757
undo_redo->create_action(TTR("Change Input Port Type"));
2758
undo_redo->add_do_method(node.ptr(), "set_input_port_type", p_port, p_type);
2759
undo_redo->add_undo_method(node.ptr(), "set_input_port_type", p_port, node->get_input_port_type(p_port));
2760
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2761
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2762
undo_redo->commit_action();
2763
}
2764
2765
void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_port) {
2766
VisualShader::Type type = get_current_shader_type();
2767
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2768
if (node.is_null()) {
2769
return;
2770
}
2771
2772
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2773
undo_redo->create_action(TTR("Change Output Port Type"));
2774
undo_redo->add_do_method(node.ptr(), "set_output_port_type", p_port, p_type);
2775
undo_redo->add_undo_method(node.ptr(), "set_output_port_type", p_port, node->get_output_port_type(p_port));
2776
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2777
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2778
undo_redo->commit_action();
2779
}
2780
2781
void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *p_line_edit, int p_node_id, int p_port_id) {
2782
VisualShader::Type type = get_current_shader_type();
2783
2784
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
2785
ERR_FAIL_COND(node.is_null());
2786
2787
String prev_name = node->get_input_port_name(p_port_id);
2788
if (prev_name == p_text) {
2789
return;
2790
}
2791
2792
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
2793
ERR_FAIL_NULL(line_edit);
2794
2795
String validated_name = visual_shader->validate_port_name(p_text, node.ptr(), p_port_id, false);
2796
if (validated_name.is_empty() || prev_name == validated_name) {
2797
line_edit->set_text(node->get_input_port_name(p_port_id));
2798
return;
2799
}
2800
2801
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2802
undo_redo->create_action(TTR("Change Input Port Name"));
2803
undo_redo->add_do_method(node.ptr(), "set_input_port_name", p_port_id, validated_name);
2804
undo_redo->add_undo_method(node.ptr(), "set_input_port_name", p_port_id, node->get_input_port_name(p_port_id));
2805
undo_redo->commit_action();
2806
}
2807
2808
void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *p_line_edit, int p_node_id, int p_port_id) {
2809
VisualShader::Type type = get_current_shader_type();
2810
2811
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id);
2812
ERR_FAIL_COND(node.is_null());
2813
2814
String prev_name = node->get_output_port_name(p_port_id);
2815
if (prev_name == p_text) {
2816
return;
2817
}
2818
2819
LineEdit *line_edit = Object::cast_to<LineEdit>(p_line_edit);
2820
ERR_FAIL_NULL(line_edit);
2821
2822
String validated_name = visual_shader->validate_port_name(p_text, node.ptr(), p_port_id, true);
2823
if (validated_name.is_empty() || prev_name == validated_name) {
2824
line_edit->set_text(node->get_output_port_name(p_port_id));
2825
return;
2826
}
2827
2828
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2829
undo_redo->create_action(TTR("Change Output Port Name"));
2830
undo_redo->add_do_method(node.ptr(), "set_output_port_name", p_port_id, validated_name);
2831
undo_redo->add_undo_method(node.ptr(), "set_output_port_name", p_port_id, prev_name);
2832
undo_redo->commit_action();
2833
}
2834
2835
void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expand) {
2836
VisualShader::Type type = get_current_shader_type();
2837
2838
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
2839
ERR_FAIL_COND(node.is_null());
2840
2841
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2842
if (p_expand) {
2843
undo_redo->create_action(TTR("Expand Output Port"));
2844
} else {
2845
undo_redo->create_action(TTR("Shrink Output Port"));
2846
}
2847
2848
undo_redo->add_do_method(node.ptr(), "_set_output_port_expanded", p_port, p_expand);
2849
undo_redo->add_undo_method(node.ptr(), "_set_output_port_expanded", p_port, !p_expand);
2850
2851
int type_size = 0;
2852
switch (node->get_output_port_type(p_port)) {
2853
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
2854
type_size = 2;
2855
} break;
2856
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
2857
type_size = 3;
2858
} break;
2859
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
2860
type_size = 4;
2861
} break;
2862
default:
2863
break;
2864
}
2865
2866
List<VisualShader::Connection> conns;
2867
visual_shader->get_node_connections(type, &conns);
2868
2869
for (const VisualShader::Connection &E : conns) {
2870
int cn_from_node = E.from_node;
2871
int cn_from_port = E.from_port;
2872
int cn_to_node = E.to_node;
2873
int cn_to_port = E.to_port;
2874
2875
if (cn_from_node == p_node) {
2876
if (p_expand) {
2877
if (cn_from_port > p_port) { // reconnect ports after expanded ports
2878
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2879
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2880
2881
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2882
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2883
2884
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);
2885
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);
2886
2887
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);
2888
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);
2889
}
2890
} else {
2891
if (cn_from_port > p_port + type_size) { // reconnect ports after expanded ports
2892
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2893
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2894
2895
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2896
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2897
2898
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);
2899
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);
2900
2901
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);
2902
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);
2903
} else if (cn_from_port > p_port) { // disconnect component ports
2904
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2905
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2906
2907
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2908
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2909
}
2910
}
2911
}
2912
}
2913
2914
int preview_port = node->get_output_port_for_preview();
2915
if (p_expand) {
2916
if (preview_port > p_port) {
2917
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port + type_size);
2918
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
2919
}
2920
} else {
2921
if (preview_port > p_port + type_size) {
2922
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - type_size);
2923
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
2924
}
2925
}
2926
2927
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2928
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2929
undo_redo->commit_action();
2930
}
2931
2932
void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
2933
VisualShader::Type type = get_current_shader_type();
2934
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2935
if (node.is_null()) {
2936
return;
2937
}
2938
2939
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2940
undo_redo->create_action(TTR("Remove Input Port"));
2941
2942
List<VisualShader::Connection> conns;
2943
visual_shader->get_node_connections(type, &conns);
2944
for (const VisualShader::Connection &E : conns) {
2945
int cn_from_node = E.from_node;
2946
int cn_from_port = E.from_port;
2947
int cn_to_node = E.to_node;
2948
int cn_to_port = E.to_port;
2949
2950
if (cn_to_node == p_node) {
2951
if (cn_to_port == p_port) {
2952
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2953
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2954
2955
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2956
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2957
} else if (cn_to_port > p_port) {
2958
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2959
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2960
2961
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2962
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
2963
2964
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);
2965
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
2966
2967
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
2968
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port - 1);
2969
}
2970
}
2971
}
2972
2973
undo_redo->add_do_method(node.ptr(), "remove_input_port", p_port);
2974
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));
2975
2976
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
2977
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
2978
2979
undo_redo->commit_action();
2980
}
2981
2982
void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
2983
VisualShader::Type type = get_current_shader_type();
2984
Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node);
2985
if (node.is_null()) {
2986
return;
2987
}
2988
2989
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
2990
undo_redo->create_action(TTR("Remove Output Port"));
2991
2992
List<VisualShader::Connection> conns;
2993
visual_shader->get_node_connections(type, &conns);
2994
for (const VisualShader::Connection &E : conns) {
2995
int cn_from_node = E.from_node;
2996
int cn_from_port = E.from_port;
2997
int cn_to_node = E.to_node;
2998
int cn_to_port = E.to_port;
2999
3000
if (cn_from_node == p_node) {
3001
if (cn_from_port == p_port) {
3002
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3003
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3004
3005
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3006
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3007
} else if (cn_from_port > p_port) {
3008
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3009
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes_forced", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3010
3011
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3012
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
3013
3014
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);
3015
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3016
3017
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3018
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port - 1, cn_to_node, cn_to_port);
3019
}
3020
}
3021
}
3022
3023
int preview_port = node->get_output_port_for_preview();
3024
if (preview_port != -1) {
3025
if (preview_port == p_port) {
3026
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", -1);
3027
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
3028
} else if (preview_port > p_port) {
3029
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", preview_port - 1);
3030
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", preview_port);
3031
}
3032
}
3033
3034
undo_redo->add_do_method(node.ptr(), "remove_output_port", p_port);
3035
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));
3036
3037
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
3038
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
3039
3040
undo_redo->commit_action();
3041
}
3042
3043
void VisualShaderEditor::_expression_focus_out(Object *p_code_edit, int p_node) {
3044
VisualShader::Type type = get_current_shader_type();
3045
Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node);
3046
if (node.is_null()) {
3047
return;
3048
}
3049
3050
CodeEdit *expression_box = Object::cast_to<CodeEdit>(p_code_edit);
3051
3052
if (node->get_expression() == expression_box->get_text()) {
3053
return;
3054
}
3055
3056
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3057
undo_redo->create_action(TTR("Set VisualShader Expression"));
3058
undo_redo->add_do_method(node.ptr(), "set_expression", expression_box->get_text());
3059
undo_redo->add_undo_method(node.ptr(), "set_expression", node->get_expression());
3060
undo_redo->add_do_method(graph_plugin.ptr(), "set_expression", type, p_node, expression_box->get_text());
3061
undo_redo->add_undo_method(graph_plugin.ptr(), "set_expression", type, p_node, node->get_expression());
3062
undo_redo->commit_action();
3063
}
3064
3065
void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) {
3066
VisualShader::Type type = VisualShader::Type(p_type);
3067
Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(type, p_node);
3068
if (node.is_null()) {
3069
return;
3070
}
3071
3072
Size2 size = p_size;
3073
if (!node->is_allow_v_resize()) {
3074
size.y = 0;
3075
}
3076
3077
node->set_size(size);
3078
3079
if (get_current_shader_type() == type) {
3080
Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
3081
Control *text_box = nullptr;
3082
if (expression_node.is_valid()) {
3083
text_box = expression_node->is_ctrl_pressed(0);
3084
if (text_box) {
3085
text_box->set_custom_minimum_size(Size2(0, 0));
3086
}
3087
}
3088
3089
GraphElement *graph_element = nullptr;
3090
Node *node2 = graph->get_node(itos(p_node));
3091
graph_element = Object::cast_to<GraphElement>(node2);
3092
if (!graph_element) {
3093
return;
3094
}
3095
3096
graph_element->set_size(size);
3097
}
3098
3099
// Update all parent frames.
3100
graph_plugin->update_frames(type, p_node);
3101
}
3102
3103
// Called once after the node was resized.
3104
void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) {
3105
Ref<VisualShaderNodeResizableBase> node = visual_shader->get_node(VisualShader::Type(p_type), p_node);
3106
if (node.is_null()) {
3107
return;
3108
}
3109
3110
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_node(itos(p_node)));
3111
if (!graph_element) {
3112
return;
3113
}
3114
3115
Size2 size = graph_element->get_size();
3116
3117
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3118
undo_redo->create_action(TTR("Resize VisualShader Node"));
3119
undo_redo->add_do_method(this, "_set_node_size", p_type, p_node, size);
3120
undo_redo->add_undo_method(this, "_set_node_size", p_type, p_node, node->get_size());
3121
undo_redo->commit_action();
3122
}
3123
3124
void VisualShaderEditor::_preview_select_port(int p_node, int p_port) {
3125
VisualShader::Type type = get_current_shader_type();
3126
Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node);
3127
if (node.is_null()) {
3128
return;
3129
}
3130
int prev_port = node->get_output_port_for_preview();
3131
if (node->get_output_port_for_preview() == p_port) {
3132
p_port = -1; //toggle it
3133
}
3134
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3135
undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview"));
3136
undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port);
3137
undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port);
3138
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, p_node);
3139
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, p_node);
3140
undo_redo->commit_action();
3141
}
3142
3143
void VisualShaderEditor::_frame_title_popup_show(const Point2 &p_position, int p_node_id) {
3144
VisualShader::Type type = get_current_shader_type();
3145
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3146
if (node.is_null()) {
3147
return;
3148
}
3149
frame_title_change_edit->set_text(node->get_title());
3150
frame_title_change_popup->set_meta("id", p_node_id);
3151
frame_title_change_popup->set_position(p_position);
3152
frame_title_change_popup->popup();
3153
3154
// Select current text.
3155
frame_title_change_edit->grab_focus();
3156
}
3157
3158
void VisualShaderEditor::_frame_title_text_changed(const String &p_new_text) {
3159
frame_title_change_edit->reset_size();
3160
frame_title_change_popup->reset_size();
3161
}
3162
3163
void VisualShaderEditor::_frame_title_text_submitted(const String &p_new_text) {
3164
frame_title_change_popup->hide();
3165
}
3166
3167
void VisualShaderEditor::_frame_title_popup_focus_out() {
3168
frame_title_change_popup->hide();
3169
}
3170
3171
void VisualShaderEditor::_frame_title_popup_hide() {
3172
int node_id = (int)frame_title_change_popup->get_meta("id", -1);
3173
ERR_FAIL_COND(node_id == -1);
3174
3175
VisualShader::Type type = get_current_shader_type();
3176
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3177
3178
ERR_FAIL_COND(node.is_null());
3179
3180
if (node->get_title() == frame_title_change_edit->get_text()) {
3181
return; // nothing changed - ignored
3182
}
3183
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3184
undo_redo->create_action(TTR("Set Frame Title"));
3185
undo_redo->add_do_method(node.ptr(), "set_title", frame_title_change_edit->get_text());
3186
undo_redo->add_undo_method(node.ptr(), "set_title", node->get_title());
3187
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, node_id);
3188
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, node_id);
3189
undo_redo->commit_action();
3190
}
3191
3192
void VisualShaderEditor::_frame_color_enabled_changed(int p_node_id) {
3193
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
3194
3195
// The new state.
3196
bool tint_color_enabled = !popup_menu->is_item_checked(item_index);
3197
3198
popup_menu->set_item_checked(item_index, tint_color_enabled);
3199
int frame_color_item_idx = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_COLOR);
3200
if (tint_color_enabled && frame_color_item_idx == -1) {
3201
popup_menu->add_item(TTR("Set Tint Color"), NodeMenuOptions::SET_FRAME_COLOR);
3202
} else if (!tint_color_enabled && frame_color_item_idx != -1) {
3203
popup_menu->remove_item(frame_color_item_idx);
3204
}
3205
3206
VisualShader::Type type = get_current_shader_type();
3207
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3208
3209
ERR_FAIL_COND(node.is_null());
3210
3211
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3212
undo_redo->create_action(TTR("Toggle Frame Color"));
3213
undo_redo->add_do_method(node.ptr(), "set_tint_color_enabled", tint_color_enabled);
3214
undo_redo->add_undo_method(node.ptr(), "set_tint_color_enabled", node->is_tint_color_enabled());
3215
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_color_enabled", (int)type, p_node_id, tint_color_enabled);
3216
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_color_enabled", (int)type, p_node_id, node->is_tint_color_enabled());
3217
undo_redo->commit_action();
3218
}
3219
3220
void VisualShaderEditor::_frame_color_popup_show(const Point2 &p_position, int p_node_id) {
3221
VisualShader::Type type = get_current_shader_type();
3222
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3223
if (node.is_null()) {
3224
return;
3225
}
3226
frame_tint_color_picker->set_pick_color(node->get_tint_color());
3227
frame_tint_color_pick_popup->set_meta("id", p_node_id);
3228
frame_tint_color_pick_popup->set_position(p_position);
3229
frame_tint_color_pick_popup->popup();
3230
}
3231
3232
void VisualShaderEditor::_frame_color_confirm() {
3233
frame_tint_color_pick_popup->hide();
3234
}
3235
3236
void VisualShaderEditor::_frame_color_changed(const Color &p_color) {
3237
ERR_FAIL_COND(!frame_tint_color_pick_popup->has_meta("id"));
3238
int node_id = (int)frame_tint_color_pick_popup->get_meta("id");
3239
3240
VisualShader::Type type = get_current_shader_type();
3241
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3242
ERR_FAIL_COND(node.is_null());
3243
node->set_tint_color(p_color);
3244
graph_plugin->set_frame_color(type, node_id, p_color);
3245
}
3246
3247
void VisualShaderEditor::_frame_color_popup_hide() {
3248
ERR_FAIL_COND(!frame_tint_color_pick_popup->has_meta("id"));
3249
int node_id = (int)frame_tint_color_pick_popup->get_meta("id");
3250
3251
VisualShader::Type type = get_current_shader_type();
3252
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, node_id);
3253
ERR_FAIL_COND(node.is_null());
3254
3255
if (node->get_tint_color() == frame_tint_color_picker->get_pick_color()) {
3256
return;
3257
}
3258
3259
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3260
undo_redo->create_action(TTR("Set Frame Color"));
3261
undo_redo->add_do_method(node.ptr(), "set_tint_color", frame_tint_color_picker->get_pick_color());
3262
undo_redo->add_undo_method(node.ptr(), "set_tint_color", node->get_tint_color());
3263
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_color", (int)type, node_id, frame_tint_color_picker->get_pick_color());
3264
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_color", (int)type, node_id, node->get_tint_color());
3265
undo_redo->commit_action();
3266
}
3267
3268
void VisualShaderEditor::_frame_autoshrink_enabled_changed(int p_node_id) {
3269
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
3270
3271
bool autoshrink_enabled = popup_menu->is_item_checked(item_index);
3272
3273
popup_menu->set_item_checked(item_index, !autoshrink_enabled);
3274
3275
VisualShader::Type type = get_current_shader_type();
3276
Ref<VisualShaderNodeFrame> node = visual_shader->get_node(type, p_node_id);
3277
3278
ERR_FAIL_COND(node.is_null());
3279
3280
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3281
undo_redo->create_action(TTR("Toggle Auto Shrink"));
3282
undo_redo->add_do_method(node.ptr(), "set_autoshrink_enabled", !autoshrink_enabled);
3283
undo_redo->add_undo_method(node.ptr(), "set_autoshrink_enabled", autoshrink_enabled);
3284
undo_redo->add_do_method(graph_plugin.ptr(), "set_frame_autoshrink_enabled", (int)type, p_node_id, !autoshrink_enabled);
3285
undo_redo->add_undo_method(graph_plugin.ptr(), "set_frame_autoshrink_enabled", (int)type, p_node_id, autoshrink_enabled);
3286
undo_redo->commit_action();
3287
3288
popup_menu->hide();
3289
}
3290
3291
void VisualShaderEditor::_parameter_line_edit_changed(const String &p_text, int p_node_id) {
3292
VisualShader::Type type = get_current_shader_type();
3293
3294
Ref<VisualShaderNodeParameter> node = visual_shader->get_node(type, p_node_id);
3295
ERR_FAIL_COND(node.is_null());
3296
3297
String validated_name = visual_shader->validate_parameter_name(p_text, node);
3298
3299
if (validated_name == node->get_parameter_name()) {
3300
return;
3301
}
3302
3303
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3304
undo_redo->create_action(TTR("Set Parameter Name"));
3305
undo_redo->add_do_method(node.ptr(), "set_parameter_name", validated_name);
3306
undo_redo->add_undo_method(node.ptr(), "set_parameter_name", node->get_parameter_name());
3307
undo_redo->add_do_method(graph_plugin.ptr(), "set_parameter_name", type, p_node_id, validated_name);
3308
undo_redo->add_undo_method(graph_plugin.ptr(), "set_parameter_name", type, p_node_id, node->get_parameter_name());
3309
undo_redo->add_do_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id);
3310
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id);
3311
3312
undo_redo->add_do_method(this, "_update_parameters", true);
3313
undo_redo->add_undo_method(this, "_update_parameters", true);
3314
3315
HashSet<String> changed_names;
3316
changed_names.insert(node->get_parameter_name());
3317
_update_parameter_refs(changed_names);
3318
3319
undo_redo->commit_action();
3320
}
3321
3322
void VisualShaderEditor::_parameter_line_edit_focus_out(Object *line_edit, int p_node_id) {
3323
_parameter_line_edit_changed(Object::cast_to<LineEdit>(line_edit)->get_text(), p_node_id);
3324
}
3325
3326
void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) {
3327
if (!p_output) {
3328
_change_input_port_name(Object::cast_to<LineEdit>(line_edit)->get_text(), line_edit, p_node_id, p_port_id);
3329
} else {
3330
_change_output_port_name(Object::cast_to<LineEdit>(line_edit)->get_text(), line_edit, p_node_id, p_port_id);
3331
}
3332
}
3333
3334
void VisualShaderEditor::_port_edited(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
3335
VisualShader::Type type = get_current_shader_type();
3336
Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node);
3337
ERR_FAIL_COND(vsn.is_null());
3338
3339
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3340
undo_redo->create_action(TTR("Set Input Default Port"));
3341
3342
Ref<VisualShaderNodeCustom> custom = Object::cast_to<VisualShaderNodeCustom>(vsn.ptr());
3343
if (custom.is_valid()) {
3344
undo_redo->add_do_method(custom.ptr(), "_set_input_port_default_value", editing_port, p_value);
3345
undo_redo->add_undo_method(custom.ptr(), "_set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
3346
} else {
3347
undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, p_value);
3348
undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port));
3349
}
3350
undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, p_value);
3351
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));
3352
undo_redo->commit_action();
3353
}
3354
3355
void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) {
3356
VisualShader::Type type = get_current_shader_type();
3357
Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, p_node);
3358
Variant value = vs_node->get_input_port_default_value(p_port);
3359
3360
edited_property_holder->set_edited_property(value);
3361
editing_node = p_node;
3362
editing_port = p_port;
3363
3364
if (property_editor) {
3365
property_editor->disconnect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
3366
property_editor_popup->remove_child(property_editor);
3367
}
3368
3369
// TODO: Define these properties with actual PropertyInfo and feed it to the property editor widget.
3370
property_editor = EditorInspector::instantiate_property_editor(edited_property_holder.ptr(), value.get_type(), "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE, true);
3371
ERR_FAIL_NULL_MSG(property_editor, "Failed to create property editor for type: " + Variant::get_type_name(value.get_type()));
3372
3373
// Determine the best size for the popup based on the property type.
3374
// 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.
3375
Size2 popup_pref_size;
3376
switch (value.get_type()) {
3377
case Variant::VECTOR3:
3378
case Variant::BASIS:
3379
popup_pref_size.width = 320;
3380
break;
3381
case Variant::VECTOR4:
3382
case Variant::PLANE:
3383
case Variant::TRANSFORM2D:
3384
case Variant::TRANSFORM3D:
3385
case Variant::PROJECTION:
3386
popup_pref_size.width = 480;
3387
break;
3388
default:
3389
popup_pref_size.width = 180;
3390
break;
3391
}
3392
property_editor_popup->set_min_size(popup_pref_size * EDSCALE);
3393
3394
property_editor->set_object_and_property(edited_property_holder.ptr(), "edited_property");
3395
property_editor->update_property();
3396
property_editor->set_name_split_ratio(0);
3397
property_editor_popup->add_child(property_editor);
3398
3399
property_editor->connect("property_changed", callable_mp(this, &VisualShaderEditor::_port_edited));
3400
3401
Button *button = Object::cast_to<Button>(p_button);
3402
if (button) {
3403
property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom());
3404
}
3405
property_editor_popup->reset_size();
3406
if (button) {
3407
property_editor_popup->popup();
3408
} else {
3409
property_editor_popup->popup_centered_ratio();
3410
}
3411
property_editor->select(0); // Focus the first focusable control.
3412
}
3413
3414
void VisualShaderEditor::_set_custom_node_option(int p_index, int p_node, int p_op) {
3415
VisualShader::Type type = get_current_shader_type();
3416
Ref<VisualShaderNodeCustom> node = visual_shader->get_node(type, p_node);
3417
if (node.is_null()) {
3418
return;
3419
}
3420
3421
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3422
undo_redo->create_action(TTR("Set Custom Node Option"));
3423
undo_redo->add_do_method(node.ptr(), "_set_option_index", p_op, p_index);
3424
undo_redo->add_undo_method(node.ptr(), "_set_option_index", p_op, node->get_option_index(p_op));
3425
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, p_node);
3426
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, p_node);
3427
undo_redo->commit_action();
3428
}
3429
3430
void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, const Vector<Variant> &p_ops) {
3431
// INPUT
3432
{
3433
VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(p_node);
3434
3435
if (input) {
3436
ERR_FAIL_COND(!p_ops[0].is_string());
3437
input->set_input_name((String)p_ops[0]);
3438
return;
3439
}
3440
}
3441
3442
// FLOAT_CONST
3443
{
3444
VisualShaderNodeFloatConstant *float_const = Object::cast_to<VisualShaderNodeFloatConstant>(p_node);
3445
3446
if (float_const) {
3447
ERR_FAIL_COND(p_ops[0].get_type() != Variant::FLOAT);
3448
float_const->set_constant((float)p_ops[0]);
3449
return;
3450
}
3451
}
3452
3453
// FLOAT_OP
3454
{
3455
VisualShaderNodeFloatOp *float_op = Object::cast_to<VisualShaderNodeFloatOp>(p_node);
3456
3457
if (float_op) {
3458
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3459
float_op->set_operator((VisualShaderNodeFloatOp::Operator)(int)p_ops[0]);
3460
return;
3461
}
3462
}
3463
3464
// FLOAT_FUNC
3465
{
3466
VisualShaderNodeFloatFunc *float_func = Object::cast_to<VisualShaderNodeFloatFunc>(p_node);
3467
3468
if (float_func) {
3469
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3470
float_func->set_function((VisualShaderNodeFloatFunc::Function)(int)p_ops[0]);
3471
return;
3472
}
3473
}
3474
3475
// VECTOR_OP
3476
{
3477
VisualShaderNodeVectorOp *vec_op = Object::cast_to<VisualShaderNodeVectorOp>(p_node);
3478
3479
if (vec_op) {
3480
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3481
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3482
vec_op->set_operator((VisualShaderNodeVectorOp::Operator)(int)p_ops[0]);
3483
vec_op->set_op_type((VisualShaderNodeVectorOp::OpType)(int)p_ops[1]);
3484
return;
3485
}
3486
}
3487
3488
// VECTOR_FUNC
3489
{
3490
VisualShaderNodeVectorFunc *vec_func = Object::cast_to<VisualShaderNodeVectorFunc>(p_node);
3491
3492
if (vec_func) {
3493
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3494
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3495
vec_func->set_function((VisualShaderNodeVectorFunc::Function)(int)p_ops[0]);
3496
vec_func->set_op_type((VisualShaderNodeVectorFunc::OpType)(int)p_ops[1]);
3497
return;
3498
}
3499
}
3500
3501
// COLOR_OP
3502
{
3503
VisualShaderNodeColorOp *color_op = Object::cast_to<VisualShaderNodeColorOp>(p_node);
3504
3505
if (color_op) {
3506
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3507
color_op->set_operator((VisualShaderNodeColorOp::Operator)(int)p_ops[0]);
3508
return;
3509
}
3510
}
3511
3512
// COLOR_FUNC
3513
{
3514
VisualShaderNodeColorFunc *color_func = Object::cast_to<VisualShaderNodeColorFunc>(p_node);
3515
3516
if (color_func) {
3517
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3518
color_func->set_function((VisualShaderNodeColorFunc::Function)(int)p_ops[0]);
3519
return;
3520
}
3521
}
3522
3523
// INT_OP
3524
{
3525
VisualShaderNodeIntOp *int_op = Object::cast_to<VisualShaderNodeIntOp>(p_node);
3526
3527
if (int_op) {
3528
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3529
int_op->set_operator((VisualShaderNodeIntOp::Operator)(int)p_ops[0]);
3530
return;
3531
}
3532
}
3533
3534
// INT_FUNC
3535
{
3536
VisualShaderNodeIntFunc *int_func = Object::cast_to<VisualShaderNodeIntFunc>(p_node);
3537
3538
if (int_func) {
3539
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3540
int_func->set_function((VisualShaderNodeIntFunc::Function)(int)p_ops[0]);
3541
return;
3542
}
3543
}
3544
3545
// UINT_OP
3546
{
3547
VisualShaderNodeUIntOp *uint_op = Object::cast_to<VisualShaderNodeUIntOp>(p_node);
3548
3549
if (uint_op) {
3550
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3551
uint_op->set_operator((VisualShaderNodeUIntOp::Operator)(int)p_ops[0]);
3552
return;
3553
}
3554
}
3555
3556
// UINT_FUNC
3557
{
3558
VisualShaderNodeUIntFunc *uint_func = Object::cast_to<VisualShaderNodeUIntFunc>(p_node);
3559
3560
if (uint_func) {
3561
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3562
uint_func->set_function((VisualShaderNodeUIntFunc::Function)(int)p_ops[0]);
3563
return;
3564
}
3565
}
3566
3567
// TRANSFORM_OP
3568
{
3569
VisualShaderNodeTransformOp *mat_op = Object::cast_to<VisualShaderNodeTransformOp>(p_node);
3570
3571
if (mat_op) {
3572
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3573
mat_op->set_operator((VisualShaderNodeTransformOp::Operator)(int)p_ops[0]);
3574
return;
3575
}
3576
}
3577
3578
// TRANSFORM_FUNC
3579
{
3580
VisualShaderNodeTransformFunc *mat_func = Object::cast_to<VisualShaderNodeTransformFunc>(p_node);
3581
3582
if (mat_func) {
3583
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3584
mat_func->set_function((VisualShaderNodeTransformFunc::Function)(int)p_ops[0]);
3585
return;
3586
}
3587
}
3588
3589
// VECTOR_COMPOSE
3590
{
3591
VisualShaderNodeVectorCompose *vec_compose = Object::cast_to<VisualShaderNodeVectorCompose>(p_node);
3592
3593
if (vec_compose) {
3594
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3595
vec_compose->set_op_type((VisualShaderNodeVectorCompose::OpType)(int)p_ops[0]);
3596
return;
3597
}
3598
}
3599
3600
// VECTOR_DECOMPOSE
3601
{
3602
VisualShaderNodeVectorDecompose *vec_decompose = Object::cast_to<VisualShaderNodeVectorDecompose>(p_node);
3603
3604
if (vec_decompose) {
3605
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3606
vec_decompose->set_op_type((VisualShaderNodeVectorDecompose::OpType)(int)p_ops[0]);
3607
return;
3608
}
3609
}
3610
3611
// UV_FUNC
3612
{
3613
VisualShaderNodeUVFunc *uv_func = Object::cast_to<VisualShaderNodeUVFunc>(p_node);
3614
3615
if (uv_func) {
3616
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3617
uv_func->set_function((VisualShaderNodeUVFunc::Function)(int)p_ops[0]);
3618
return;
3619
}
3620
}
3621
3622
// IS
3623
{
3624
VisualShaderNodeIs *is = Object::cast_to<VisualShaderNodeIs>(p_node);
3625
3626
if (is) {
3627
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3628
is->set_function((VisualShaderNodeIs::Function)(int)p_ops[0]);
3629
return;
3630
}
3631
}
3632
3633
// COMPARE
3634
{
3635
VisualShaderNodeCompare *cmp = Object::cast_to<VisualShaderNodeCompare>(p_node);
3636
3637
if (cmp) {
3638
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3639
cmp->set_function((VisualShaderNodeCompare::Function)(int)p_ops[0]);
3640
return;
3641
}
3642
}
3643
3644
// DISTANCE
3645
{
3646
VisualShaderNodeVectorDistance *dist = Object::cast_to<VisualShaderNodeVectorDistance>(p_node);
3647
3648
if (dist) {
3649
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3650
dist->set_op_type((VisualShaderNodeVectorDistance::OpType)(int)p_ops[0]);
3651
return;
3652
}
3653
}
3654
3655
// DERIVATIVE
3656
{
3657
VisualShaderNodeDerivativeFunc *der_func = Object::cast_to<VisualShaderNodeDerivativeFunc>(p_node);
3658
3659
if (der_func) {
3660
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3661
ERR_FAIL_COND(p_ops[1].get_type() != Variant::INT);
3662
der_func->set_function((VisualShaderNodeDerivativeFunc::Function)(int)p_ops[0]);
3663
der_func->set_op_type((VisualShaderNodeDerivativeFunc::OpType)(int)p_ops[1]);
3664
return;
3665
}
3666
}
3667
3668
// MIX
3669
{
3670
VisualShaderNodeMix *mix = Object::cast_to<VisualShaderNodeMix>(p_node);
3671
3672
if (mix) {
3673
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3674
mix->set_op_type((VisualShaderNodeMix::OpType)(int)p_ops[0]);
3675
return;
3676
}
3677
}
3678
3679
// CLAMP
3680
{
3681
VisualShaderNodeClamp *clamp_func = Object::cast_to<VisualShaderNodeClamp>(p_node);
3682
3683
if (clamp_func) {
3684
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3685
clamp_func->set_op_type((VisualShaderNodeClamp::OpType)(int)p_ops[0]);
3686
return;
3687
}
3688
}
3689
3690
// SWITCH
3691
{
3692
VisualShaderNodeSwitch *switch_func = Object::cast_to<VisualShaderNodeSwitch>(p_node);
3693
3694
if (switch_func) {
3695
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3696
switch_func->set_op_type((VisualShaderNodeSwitch::OpType)(int)p_ops[0]);
3697
return;
3698
}
3699
}
3700
3701
// FACEFORWARD
3702
{
3703
VisualShaderNodeFaceForward *face_forward = Object::cast_to<VisualShaderNodeFaceForward>(p_node);
3704
if (face_forward) {
3705
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3706
face_forward->set_op_type((VisualShaderNodeFaceForward::OpType)(int)p_ops[0]);
3707
return;
3708
}
3709
}
3710
3711
// LENGTH
3712
{
3713
VisualShaderNodeVectorLen *length = Object::cast_to<VisualShaderNodeVectorLen>(p_node);
3714
if (length) {
3715
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3716
length->set_op_type((VisualShaderNodeVectorLen::OpType)(int)p_ops[0]);
3717
return;
3718
}
3719
}
3720
3721
// SMOOTHSTEP
3722
{
3723
VisualShaderNodeSmoothStep *smooth_step_func = Object::cast_to<VisualShaderNodeSmoothStep>(p_node);
3724
3725
if (smooth_step_func) {
3726
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3727
smooth_step_func->set_op_type((VisualShaderNodeSmoothStep::OpType)(int)p_ops[0]);
3728
return;
3729
}
3730
}
3731
3732
// STEP
3733
{
3734
VisualShaderNodeStep *step_func = Object::cast_to<VisualShaderNodeStep>(p_node);
3735
3736
if (step_func) {
3737
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3738
step_func->set_op_type((VisualShaderNodeStep::OpType)(int)p_ops[0]);
3739
return;
3740
}
3741
}
3742
3743
// MULTIPLY_ADD
3744
{
3745
VisualShaderNodeMultiplyAdd *fma_func = Object::cast_to<VisualShaderNodeMultiplyAdd>(p_node);
3746
3747
if (fma_func) {
3748
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3749
fma_func->set_op_type((VisualShaderNodeMultiplyAdd::OpType)(int)p_ops[0]);
3750
}
3751
}
3752
3753
// REMAP
3754
{
3755
VisualShaderNodeRemap *remap_func = Object::cast_to<VisualShaderNodeRemap>(p_node);
3756
3757
if (remap_func) {
3758
ERR_FAIL_COND(p_ops[0].get_type() != Variant::INT);
3759
remap_func->set_op_type((VisualShaderNodeRemap::OpType)(int)p_ops[0]);
3760
}
3761
}
3762
}
3763
3764
void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, const String &p_resource_path, int p_node_idx) {
3765
ERR_FAIL_INDEX(p_idx, add_options.size());
3766
3767
VisualShader::Type type = get_current_shader_type();
3768
3769
Ref<VisualShaderNode> vsnode;
3770
3771
bool is_custom = add_options[p_idx].is_custom;
3772
3773
if (!is_custom && !add_options[p_idx].type.is_empty()) {
3774
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instantiate(add_options[p_idx].type));
3775
ERR_FAIL_NULL(vsn);
3776
if (!p_ops.is_empty()) {
3777
_setup_node(vsn, p_ops);
3778
}
3779
VisualShaderNodeParameterRef *parameter_ref = Object::cast_to<VisualShaderNodeParameterRef>(vsn);
3780
if (parameter_ref && to_node != -1 && to_slot != -1) {
3781
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
3782
bool success = false;
3783
3784
for (int i = 0; i < parameter_ref->get_parameters_count(); i++) {
3785
if (parameter_ref->get_port_type_by_index(i) == input_port_type) {
3786
parameter_ref->set_parameter_name(parameter_ref->get_parameter_name_by_index(i));
3787
success = true;
3788
break;
3789
}
3790
}
3791
if (!success) {
3792
for (int i = 0; i < parameter_ref->get_parameters_count(); i++) {
3793
if (visual_shader->is_port_types_compatible(parameter_ref->get_port_type_by_index(i), input_port_type)) {
3794
parameter_ref->set_parameter_name(parameter_ref->get_parameter_name_by_index(i));
3795
break;
3796
}
3797
}
3798
}
3799
}
3800
3801
vsnode = Ref<VisualShaderNode>(vsn);
3802
} else {
3803
StringName base_type;
3804
bool is_native = add_options[p_idx].is_native;
3805
3806
if (is_native) {
3807
base_type = add_options[p_idx].type;
3808
} else {
3809
ERR_FAIL_COND(add_options[p_idx].script.is_null());
3810
base_type = add_options[p_idx].script->get_instance_base_type();
3811
}
3812
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instantiate(base_type));
3813
ERR_FAIL_NULL(vsn);
3814
vsnode = Ref<VisualShaderNode>(vsn);
3815
if (!is_native) {
3816
vsnode->set_script(add_options[p_idx].script);
3817
}
3818
VisualShaderNodeCustom *custom_node = Object::cast_to<VisualShaderNodeCustom>(vsn);
3819
ERR_FAIL_NULL(custom_node);
3820
custom_node->update_property_default_values();
3821
custom_node->update_input_port_default_values();
3822
custom_node->update_properties();
3823
}
3824
3825
bool is_texture2d = (Object::cast_to<VisualShaderNodeTexture>(vsnode.ptr()) != nullptr);
3826
bool is_texture3d = (Object::cast_to<VisualShaderNodeTexture3D>(vsnode.ptr()) != nullptr);
3827
bool is_texture2d_array = (Object::cast_to<VisualShaderNodeTexture2DArray>(vsnode.ptr()) != nullptr);
3828
bool is_cubemap = (Object::cast_to<VisualShaderNodeCubemap>(vsnode.ptr()) != nullptr);
3829
bool is_curve = (Object::cast_to<VisualShaderNodeCurveTexture>(vsnode.ptr()) != nullptr);
3830
bool is_curve_xyz = (Object::cast_to<VisualShaderNodeCurveXYZTexture>(vsnode.ptr()) != nullptr);
3831
bool is_parameter = (Object::cast_to<VisualShaderNodeParameter>(vsnode.ptr()) != nullptr);
3832
bool is_mesh_emitter = (Object::cast_to<VisualShaderNodeParticleMeshEmitter>(vsnode.ptr()) != nullptr);
3833
3834
Point2 position = graph->get_scroll_offset();
3835
3836
if (saved_node_pos_dirty) {
3837
position += saved_node_pos;
3838
} else {
3839
position += graph->get_size() * 0.5;
3840
position /= EDSCALE;
3841
}
3842
position /= graph->get_zoom();
3843
saved_node_pos_dirty = false;
3844
3845
int id_to_use = visual_shader->get_valid_node_id(type);
3846
3847
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
3848
if (p_resource_path.is_empty()) {
3849
undo_redo->create_action(TTR("Add Node to Visual Shader"));
3850
} else {
3851
id_to_use += p_node_idx;
3852
}
3853
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use);
3854
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use);
3855
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use, false, true);
3856
undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_to_use, false);
3857
3858
VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr());
3859
if (expr) {
3860
expr->set_size(Size2(250 * EDSCALE, 150 * EDSCALE));
3861
}
3862
3863
Ref<VisualShaderNodeFrame> frame = vsnode;
3864
if (frame.is_valid()) {
3865
frame->set_size(Size2(320 * EDSCALE, 180 * EDSCALE));
3866
}
3867
3868
Ref<VisualShaderNodeReroute> reroute = vsnode;
3869
3870
bool created_expression_port = false;
3871
3872
// A node is inserted in an already present connection.
3873
if (from_node != -1 && from_slot != -1 && to_node != -1 && to_slot != -1) {
3874
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, to_node, to_slot);
3875
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, to_node, to_slot);
3876
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, to_node, to_slot);
3877
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, to_node, to_slot);
3878
}
3879
3880
// Create a connection from the output port of an existing node to the new one.
3881
if (from_node != -1 && from_slot != -1) {
3882
VisualShaderNode::PortType output_port_type = visual_shader->get_node(type, from_node)->get_output_port_type(from_slot);
3883
3884
if (expr && expr->is_editable()) {
3885
expr->add_input_port(0, output_port_type, "input0");
3886
created_expression_port = true;
3887
}
3888
3889
if (vsnode->get_input_port_count() > 0 || created_expression_port) {
3890
int _to_node = id_to_use;
3891
3892
if (created_expression_port) {
3893
int _to_slot = 0;
3894
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3895
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3896
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3897
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3898
} else {
3899
int _to_slot = -1;
3900
3901
// Attempting to connect to the default input port or to the first correct port (if it's not found).
3902
for (int i = 0; i < vsnode->get_input_port_count(); i++) {
3903
if (visual_shader->is_port_types_compatible(output_port_type, vsnode->get_input_port_type(i)) || reroute.is_valid()) {
3904
if (i == vsnode->get_default_input_port(output_port_type)) {
3905
_to_slot = i;
3906
break;
3907
} else if (_to_slot == -1) {
3908
_to_slot = i;
3909
}
3910
}
3911
}
3912
3913
if (_to_slot >= 0) {
3914
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3915
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3916
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3917
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot);
3918
}
3919
}
3920
3921
if (output_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) {
3922
if (is_texture2d) {
3923
undo_redo->force_fixed_history(); // vsnode is freshly created and has no path, so history can't be correctly determined.
3924
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeTexture::SOURCE_PORT);
3925
}
3926
if (is_texture3d || is_texture2d_array) {
3927
undo_redo->force_fixed_history();
3928
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeSample3D::SOURCE_PORT);
3929
}
3930
if (is_cubemap) {
3931
undo_redo->force_fixed_history();
3932
undo_redo->add_do_method(vsnode.ptr(), "set_source", VisualShaderNodeCubemap::SOURCE_PORT);
3933
}
3934
}
3935
}
3936
}
3937
3938
// Create a connection from the new node to an input port of an existing one.
3939
if (to_node != -1 && to_slot != -1) {
3940
VisualShaderNode::PortType input_port_type = visual_shader->get_node(type, to_node)->get_input_port_type(to_slot);
3941
3942
if (expr && expr->is_editable() && input_port_type != VisualShaderNode::PORT_TYPE_SAMPLER) {
3943
expr->add_output_port(0, input_port_type, "output0");
3944
String initial_expression_code;
3945
3946
switch (input_port_type) {
3947
case VisualShaderNode::PORT_TYPE_SCALAR:
3948
initial_expression_code = "output0 = 1.0;";
3949
break;
3950
case VisualShaderNode::PORT_TYPE_SCALAR_INT:
3951
initial_expression_code = "output0 = 1;";
3952
break;
3953
case VisualShaderNode::PORT_TYPE_SCALAR_UINT:
3954
initial_expression_code = "output0 = 1u;";
3955
break;
3956
case VisualShaderNode::PORT_TYPE_VECTOR_2D:
3957
initial_expression_code = "output0 = vec2(1.0, 1.0);";
3958
break;
3959
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
3960
initial_expression_code = "output0 = vec3(1.0, 1.0, 1.0);";
3961
break;
3962
case VisualShaderNode::PORT_TYPE_VECTOR_4D:
3963
initial_expression_code = "output0 = vec4(1.0, 1.0, 1.0, 1.0);";
3964
break;
3965
case VisualShaderNode::PORT_TYPE_BOOLEAN:
3966
initial_expression_code = "output0 = true;";
3967
break;
3968
case VisualShaderNode::PORT_TYPE_TRANSFORM:
3969
initial_expression_code = "output0 = mat4(1.0);";
3970
break;
3971
default:
3972
break;
3973
}
3974
3975
expr->set_expression(initial_expression_code);
3976
expr->set_size(Size2(500 * EDSCALE, 200 * EDSCALE));
3977
created_expression_port = true;
3978
}
3979
if (vsnode->get_output_port_count() > 0 || created_expression_port) {
3980
int _from_node = id_to_use;
3981
3982
if (created_expression_port) {
3983
int _from_slot = 0;
3984
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
3985
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
3986
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot);
3987
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot);
3988
} else {
3989
// Need to setting up Input node properly before committing since `is_port_types_compatible` (calling below) is using `mode` and `shader_type`.
3990
VisualShaderNodeInput *input = Object::cast_to<VisualShaderNodeInput>(vsnode.ptr());
3991
if (input) {
3992
input->set_shader_mode(visual_shader->get_mode());
3993
input->set_shader_type(get_current_shader_type());
3994
}
3995
3996
// Attempting to connect to the first correct port.
3997
for (int i = 0; i < vsnode->get_output_port_count(); i++) {
3998
if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(i), input_port_type) || reroute.is_valid()) {
3999
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
4000
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, i, to_node, to_slot);
4001
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, i, to_node, to_slot);
4002
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, i, to_node, to_slot);
4003
break;
4004
}
4005
}
4006
}
4007
}
4008
}
4009
4010
_member_cancel();
4011
4012
if (is_parameter) {
4013
undo_redo->add_do_method(this, "_update_parameters", true);
4014
undo_redo->add_undo_method(this, "_update_parameters", true);
4015
}
4016
4017
if (is_curve) {
4018
callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve).call_deferred(id_to_use);
4019
}
4020
4021
if (is_curve_xyz) {
4022
callable_mp(graph_plugin.ptr(), &VisualShaderGraphPlugin::update_curve_xyz).call_deferred(id_to_use);
4023
}
4024
4025
if (p_resource_path.is_empty()) {
4026
undo_redo->commit_action();
4027
} else {
4028
//post-initialization
4029
4030
if (is_texture2d || is_texture3d || is_curve || is_curve_xyz) {
4031
undo_redo->force_fixed_history();
4032
undo_redo->add_do_method(vsnode.ptr(), "set_texture", ResourceLoader::load(p_resource_path));
4033
return;
4034
}
4035
4036
if (is_cubemap) {
4037
undo_redo->force_fixed_history();
4038
undo_redo->add_do_method(vsnode.ptr(), "set_cube_map", ResourceLoader::load(p_resource_path));
4039
return;
4040
}
4041
4042
if (is_texture2d_array) {
4043
undo_redo->force_fixed_history();
4044
undo_redo->add_do_method(vsnode.ptr(), "set_texture_array", ResourceLoader::load(p_resource_path));
4045
return;
4046
}
4047
4048
if (is_mesh_emitter) {
4049
undo_redo->add_do_method(vsnode.ptr(), "set_mesh", ResourceLoader::load(p_resource_path));
4050
return;
4051
}
4052
}
4053
}
4054
4055
void VisualShaderEditor::_add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) {
4056
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4057
undo_redo->create_action(vformat(TTR("Add Varying to Visual Shader: %s"), p_name));
4058
4059
undo_redo->add_do_method(visual_shader.ptr(), "add_varying", p_name, p_mode, p_type);
4060
undo_redo->add_undo_method(visual_shader.ptr(), "remove_varying", p_name);
4061
4062
undo_redo->add_do_method(this, "_update_varyings");
4063
undo_redo->add_undo_method(this, "_update_varyings");
4064
4065
for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
4066
if (p_mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
4067
continue;
4068
}
4069
4070
VisualShader::Type type = VisualShader::Type(i);
4071
Vector<int> nodes = visual_shader->get_node_list(type);
4072
4073
for (int j = 0; j < nodes.size(); j++) {
4074
int node_id = nodes[j];
4075
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
4076
Ref<VisualShaderNodeVarying> var = vsnode;
4077
4078
if (var.is_valid()) {
4079
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
4080
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
4081
}
4082
}
4083
}
4084
4085
undo_redo->add_do_method(this, "_update_varying_tree");
4086
undo_redo->add_undo_method(this, "_update_varying_tree");
4087
undo_redo->commit_action();
4088
}
4089
4090
void VisualShaderEditor::_remove_varying(const String &p_name) {
4091
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4092
undo_redo->create_action(vformat(TTR("Remove Varying from Visual Shader: %s"), p_name));
4093
4094
VisualShader::VaryingMode var_mode = visual_shader->get_varying_mode(p_name);
4095
4096
undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", p_name);
4097
undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", p_name, var_mode, visual_shader->get_varying_type(p_name));
4098
4099
undo_redo->add_do_method(this, "_update_varyings");
4100
undo_redo->add_undo_method(this, "_update_varyings");
4101
4102
for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
4103
if (var_mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
4104
continue;
4105
}
4106
4107
VisualShader::Type type = VisualShader::Type(i);
4108
Vector<int> nodes = visual_shader->get_node_list(type);
4109
4110
for (int j = 0; j < nodes.size(); j++) {
4111
int node_id = nodes[j];
4112
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
4113
Ref<VisualShaderNodeVarying> var = vsnode;
4114
4115
if (var.is_valid()) {
4116
String var_name = var->get_varying_name();
4117
4118
if (var_name == p_name) {
4119
undo_redo->add_do_method(var.ptr(), "set_varying_name", "[None]");
4120
undo_redo->add_undo_method(var.ptr(), "set_varying_name", var_name);
4121
undo_redo->add_do_method(var.ptr(), "set_varying_type", VisualShader::VARYING_TYPE_FLOAT);
4122
undo_redo->add_undo_method(var.ptr(), "set_varying_type", var->get_varying_type());
4123
}
4124
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
4125
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
4126
}
4127
}
4128
4129
List<VisualShader::Connection> node_connections;
4130
visual_shader->get_node_connections(type, &node_connections);
4131
4132
for (VisualShader::Connection &E : node_connections) {
4133
Ref<VisualShaderNodeVaryingGetter> var_getter = Object::cast_to<VisualShaderNodeVaryingGetter>(visual_shader->get_node(type, E.from_node).ptr());
4134
if (var_getter.is_valid() && E.from_port > 0) {
4135
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4136
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4137
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4138
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4139
}
4140
Ref<VisualShaderNodeVaryingSetter> var_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(visual_shader->get_node(type, E.to_node).ptr());
4141
if (var_setter.is_valid() && E.to_port > 0) {
4142
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4143
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4144
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4145
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4146
}
4147
}
4148
}
4149
4150
undo_redo->add_do_method(this, "_update_varying_tree");
4151
undo_redo->add_undo_method(this, "_update_varying_tree");
4152
undo_redo->commit_action();
4153
}
4154
4155
void VisualShaderEditor::_update_varyings() {
4156
VisualShaderNodeVarying::clear_varyings(visual_shader->get_rid());
4157
4158
for (int i = 0; i < visual_shader->get_varyings_count(); i++) {
4159
const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
4160
4161
if (var != nullptr) {
4162
VisualShaderNodeVarying::add_varying(visual_shader->get_rid(), var->name, var->mode, var->type);
4163
}
4164
}
4165
}
4166
4167
void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
4168
VisualShader::Type type = get_current_shader_type();
4169
drag_buffer.push_back({ type, p_node, p_from, p_to });
4170
if (!drag_dirty) {
4171
callable_mp(this, &VisualShaderEditor::_nodes_dragged).call_deferred();
4172
}
4173
drag_dirty = true;
4174
}
4175
4176
void VisualShaderEditor::_nodes_dragged() {
4177
drag_dirty = false;
4178
4179
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4180
if (frame_node_id_to_link_to == -1) {
4181
undo_redo->create_action(TTR("Move VisualShader Node(s)"));
4182
} else {
4183
undo_redo->create_action(TTR("Move and Attach VisualShader Node(s) to parent frame"));
4184
}
4185
4186
for (const DragOp &E : drag_buffer) {
4187
undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.to);
4188
undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.from);
4189
undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.to);
4190
undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.from);
4191
}
4192
4193
for (const int node_id : nodes_link_to_frame_buffer) {
4194
VisualShader::Type type = get_current_shader_type();
4195
Ref<VisualShaderNode> vs_node = visual_shader->get_node(type, node_id);
4196
4197
undo_redo->add_do_method(visual_shader.ptr(), "attach_node_to_frame", type, node_id, frame_node_id_to_link_to);
4198
undo_redo->add_do_method(graph_plugin.ptr(), "attach_node_to_frame", type, node_id, frame_node_id_to_link_to);
4199
undo_redo->add_undo_method(graph_plugin.ptr(), "detach_node_from_frame", type, node_id);
4200
undo_redo->add_undo_method(visual_shader.ptr(), "detach_node_from_frame", type, node_id);
4201
}
4202
4203
undo_redo->commit_action();
4204
4205
_handle_node_drop_on_connection();
4206
4207
drag_buffer.clear();
4208
nodes_link_to_frame_buffer.clear();
4209
frame_node_id_to_link_to = -1;
4210
}
4211
4212
void VisualShaderEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
4213
VisualShader::Type type = get_current_shader_type();
4214
4215
int from = p_from.to_int();
4216
int to = p_to.to_int();
4217
bool swap = last_to_node != -1 && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL);
4218
4219
if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) {
4220
return;
4221
}
4222
4223
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4224
undo_redo->create_action(TTR("Nodes Connected"));
4225
4226
List<VisualShader::Connection> conns;
4227
visual_shader->get_node_connections(type, &conns);
4228
4229
for (const VisualShader::Connection &E : conns) {
4230
if (E.to_node == to && E.to_port == p_to_index) {
4231
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4232
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4233
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4234
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4235
4236
if (swap) {
4237
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4238
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4239
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4240
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, last_to_node, last_to_port);
4241
}
4242
break;
4243
}
4244
}
4245
4246
undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4247
undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4248
undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4249
undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4250
4251
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, from);
4252
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, from);
4253
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to);
4254
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to);
4255
undo_redo->commit_action();
4256
4257
last_to_node = -1;
4258
last_to_port = -1;
4259
}
4260
4261
void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) {
4262
graph->disconnect_node(p_from, p_from_index, p_to, p_to_index);
4263
4264
VisualShader::Type type = get_current_shader_type();
4265
4266
int from = p_from.to_int();
4267
int to = p_to.to_int();
4268
4269
last_to_node = to;
4270
last_to_port = p_to_index;
4271
4272
info_label->show();
4273
4274
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4275
undo_redo->create_action(TTR("Nodes Disconnected"));
4276
undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4277
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4278
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index);
4279
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index);
4280
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", (int)type, to);
4281
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", (int)type, to);
4282
undo_redo->commit_action();
4283
}
4284
4285
void VisualShaderEditor::_connection_drag_ended() {
4286
info_label->hide();
4287
}
4288
4289
void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) {
4290
from_node = p_from.to_int();
4291
from_slot = p_from_slot;
4292
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
4293
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
4294
Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), from_node);
4295
if (node.is_valid()) {
4296
output_port_type = node->get_output_port_type(from_slot);
4297
}
4298
_show_members_dialog(true, input_port_type, output_port_type);
4299
}
4300
4301
void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) {
4302
to_node = p_to.to_int();
4303
to_slot = p_to_slot;
4304
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
4305
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
4306
Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), to_node);
4307
if (node.is_valid()) {
4308
input_port_type = node->get_input_port_type(to_slot);
4309
}
4310
_show_members_dialog(true, input_port_type, output_port_type);
4311
}
4312
4313
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) {
4314
VisualShader::Type shader_type = get_current_shader_type();
4315
4316
// Get selected graph node.
4317
Ref<VisualShaderNode> selected_vsnode;
4318
int selected_node_id = -1;
4319
int selected_node_count = 0;
4320
Rect2 selected_node_rect;
4321
4322
for (int i = 0; i < graph->get_child_count(); i++) {
4323
GraphNode *graph_node = Object::cast_to<GraphNode>(graph->get_child(i));
4324
if (graph_node && graph_node->is_selected()) {
4325
selected_node_id = String(graph_node->get_name()).to_int();
4326
Ref<VisualShaderNode> vsnode = visual_shader->get_node(shader_type, selected_node_id);
4327
if (!vsnode->is_deletable()) {
4328
continue;
4329
}
4330
4331
selected_node_count += 1;
4332
4333
Ref<VisualShaderNode> node = visual_shader->get_node(shader_type, selected_node_id);
4334
selected_vsnode = node;
4335
selected_node_rect = graph_node->get_rect();
4336
}
4337
}
4338
4339
// Only a single node - which has both input and output ports but is not connected yet - can be inserted.
4340
if (selected_node_count != 1 || selected_vsnode.is_null()) {
4341
return false;
4342
}
4343
4344
// Check whether the dragged node was dropped over a connection.
4345
List<Ref<GraphEdit::Connection>> intersecting_connections = graph->get_connections_intersecting_with_rect(selected_node_rect);
4346
4347
if (intersecting_connections.is_empty()) {
4348
return false;
4349
}
4350
4351
Ref<GraphEdit::Connection> intersecting_connection = intersecting_connections.front()->get();
4352
4353
if (selected_vsnode->is_any_port_connected() || selected_vsnode->get_input_port_count() == 0 || selected_vsnode->get_output_port_count() == 0) {
4354
return false;
4355
}
4356
4357
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);
4358
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);
4359
4360
Ref<VisualShaderNodeReroute> reroute_node = selected_vsnode;
4361
4362
// Searching for the default port or the first compatible input port of the node to insert.
4363
int _to_port = -1;
4364
for (int i = 0; i < selected_vsnode->get_input_port_count(); i++) {
4365
if (visual_shader->is_port_types_compatible(original_port_type_from, selected_vsnode->get_input_port_type(i)) || reroute_node.is_valid()) {
4366
if (i == selected_vsnode->get_default_input_port(original_port_type_from)) {
4367
_to_port = i;
4368
break;
4369
} else if (_to_port == -1) {
4370
_to_port = i;
4371
}
4372
}
4373
}
4374
4375
// Searching for the first compatible output port of the node to insert.
4376
int _from_port = -1;
4377
for (int i = 0; i < selected_vsnode->get_output_port_count(); i++) {
4378
if (visual_shader->is_port_types_compatible(selected_vsnode->get_output_port_type(i), original_port_type_to) || reroute_node.is_valid()) {
4379
_from_port = i;
4380
break;
4381
}
4382
}
4383
4384
if (_to_port == -1 || _from_port == -1) {
4385
return false;
4386
}
4387
4388
if (r_closest_connection != nullptr) {
4389
*r_closest_connection = intersecting_connection;
4390
}
4391
if (r_from_port != nullptr) {
4392
*r_from_port = _from_port;
4393
}
4394
if (r_to_port != nullptr) {
4395
*r_to_port = _to_port;
4396
}
4397
4398
return true;
4399
}
4400
4401
void VisualShaderEditor::_handle_node_drop_on_connection() {
4402
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4403
undo_redo->create_action(TTR("Insert node"));
4404
4405
// Check whether the dragged node was dropped over a connection.
4406
Ref<GraphEdit::Connection> closest_connection;
4407
int _from_port = -1;
4408
int _to_port = -1;
4409
4410
if (!_check_node_drop_on_connection(graph->get_local_mouse_position(), &closest_connection, &_from_port, &_to_port)) {
4411
return;
4412
}
4413
4414
int selected_node_id = drag_buffer.front()->get().node;
4415
VisualShader::Type shader_type = get_current_shader_type();
4416
Ref<VisualShaderNode> selected_vsnode = visual_shader->get_node(shader_type, selected_node_id);
4417
4418
// Delete the old connection.
4419
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);
4420
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);
4421
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);
4422
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);
4423
4424
// Add the connection to the dropped node.
4425
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);
4426
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);
4427
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);
4428
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);
4429
4430
// Add the connection from the dropped node.
4431
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);
4432
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);
4433
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);
4434
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);
4435
4436
undo_redo->commit_action();
4437
4438
call_deferred(SNAME("_update_graph"));
4439
}
4440
4441
void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
4442
VisualShader::Type type = VisualShader::Type(p_type);
4443
List<VisualShader::Connection> conns;
4444
visual_shader->get_node_connections(type, &conns);
4445
4446
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4447
for (const int &F : p_nodes) {
4448
for (const VisualShader::Connection &E : conns) {
4449
if (E.from_node == F || E.to_node == F) {
4450
undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4451
}
4452
}
4453
}
4454
4455
// The VS nodes need to be added before attaching them to frames.
4456
for (const int &F : p_nodes) {
4457
Ref<VisualShaderNode> node = visual_shader->get_node(type, F);
4458
undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F), F);
4459
undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F, false, false);
4460
}
4461
4462
// Update frame references.
4463
for (const int &node_id : p_nodes) {
4464
Ref<VisualShaderNodeFrame> frame = visual_shader->get_node(type, node_id);
4465
if (frame.is_valid()) {
4466
for (const int &attached_node_id : frame->get_attached_nodes()) {
4467
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", type, attached_node_id);
4468
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", type, attached_node_id);
4469
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", type, attached_node_id, node_id);
4470
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", type, attached_node_id, node_id);
4471
}
4472
}
4473
4474
Ref<VisualShaderNode> node = visual_shader->get_node(type, node_id);
4475
if (node->get_frame() == -1) {
4476
continue;
4477
}
4478
4479
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", type, node_id);
4480
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", type, node_id);
4481
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", type, node_id, node->get_frame());
4482
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", type, node_id, node->get_frame());
4483
}
4484
4485
// Restore size of the frame nodes.
4486
for (const int &F : p_nodes) {
4487
Ref<VisualShaderNodeFrame> frame = visual_shader->get_node(type, F);
4488
if (frame.is_valid()) {
4489
undo_redo->add_undo_method(this, "_set_node_size", type, F, frame->get_size());
4490
}
4491
}
4492
4493
HashSet<String> parameter_names;
4494
4495
for (const int &F : p_nodes) {
4496
Ref<VisualShaderNode> node = visual_shader->get_node(type, F);
4497
4498
undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F);
4499
4500
VisualShaderNodeParameter *parameter = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4501
if (parameter) {
4502
parameter_names.insert(parameter->get_parameter_name());
4503
}
4504
}
4505
4506
List<VisualShader::Connection> used_conns;
4507
for (const int &F : p_nodes) {
4508
for (const VisualShader::Connection &E : conns) {
4509
if (E.from_node == F || E.to_node == F) {
4510
bool cancel = false;
4511
for (const VisualShader::Connection &R : used_conns) {
4512
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) {
4513
cancel = true; // to avoid ERR_ALREADY_EXISTS warning
4514
break;
4515
}
4516
}
4517
if (!cancel) {
4518
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4519
undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
4520
used_conns.push_back(E);
4521
}
4522
}
4523
}
4524
}
4525
4526
// Delete nodes from the graph.
4527
for (const int &F : p_nodes) {
4528
undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F, false);
4529
}
4530
4531
// Update parameter refs if any parameter has been deleted.
4532
if (parameter_names.size() > 0) {
4533
undo_redo->add_do_method(this, "_update_parameters", true);
4534
undo_redo->add_undo_method(this, "_update_parameters", true);
4535
4536
_update_parameter_refs(parameter_names);
4537
}
4538
}
4539
4540
void VisualShaderEditor::_replace_node(VisualShader::Type p_type_id, int p_node_id, const StringName &p_from, const StringName &p_to) {
4541
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4542
undo_redo->add_do_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_to);
4543
undo_redo->add_undo_method(visual_shader.ptr(), "replace_node", p_type_id, p_node_id, p_from);
4544
}
4545
4546
void VisualShaderEditor::_update_constant(VisualShader::Type p_type_id, int p_node_id, const Variant &p_var, int p_preview_port) {
4547
Ref<VisualShaderNode> node = visual_shader->get_node(p_type_id, p_node_id);
4548
ERR_FAIL_COND(node.is_null());
4549
ERR_FAIL_COND(!node->has_method("set_constant"));
4550
node->call("set_constant", p_var);
4551
if (p_preview_port != -1) {
4552
node->set_output_port_for_preview(p_preview_port);
4553
}
4554
}
4555
4556
void VisualShaderEditor::_update_parameter(VisualShader::Type p_type_id, int p_node_id, const Variant &p_var, int p_preview_port) {
4557
Ref<VisualShaderNodeParameter> parameter = visual_shader->get_node(p_type_id, p_node_id);
4558
ERR_FAIL_COND(parameter.is_null());
4559
4560
String valid_name = visual_shader->validate_parameter_name(parameter->get_parameter_name(), parameter);
4561
parameter->set_parameter_name(valid_name);
4562
graph_plugin->set_parameter_name(p_type_id, p_node_id, valid_name);
4563
4564
if (parameter->has_method("set_default_value_enabled")) {
4565
parameter->call("set_default_value_enabled", true);
4566
parameter->call("set_default_value", p_var);
4567
}
4568
if (p_preview_port != -1) {
4569
parameter->set_output_port_for_preview(p_preview_port);
4570
}
4571
}
4572
4573
void VisualShaderEditor::_convert_constants_to_parameters(bool p_vice_versa) {
4574
VisualShader::Type type_id = get_current_shader_type();
4575
4576
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4577
if (!p_vice_versa) {
4578
undo_redo->create_action(TTR("Convert Constant Node(s) To Parameter(s)"));
4579
} else {
4580
undo_redo->create_action(TTR("Convert Parameter Node(s) To Constant(s)"));
4581
}
4582
4583
const HashSet<int> &current_set = p_vice_versa ? selected_parameters : selected_constants;
4584
HashSet<String> deleted_names;
4585
4586
for (const int &E : current_set) {
4587
int node_id = E;
4588
Ref<VisualShaderNode> node = visual_shader->get_node(type_id, node_id);
4589
bool caught = false;
4590
Variant var;
4591
4592
// float
4593
if (!p_vice_versa) {
4594
Ref<VisualShaderNodeFloatConstant> float_const = Object::cast_to<VisualShaderNodeFloatConstant>(node.ptr());
4595
if (float_const.is_valid()) {
4596
_replace_node(type_id, node_id, "VisualShaderNodeFloatConstant", "VisualShaderNodeFloatParameter");
4597
var = float_const->get_constant();
4598
caught = true;
4599
}
4600
} else {
4601
Ref<VisualShaderNodeFloatParameter> float_parameter = Object::cast_to<VisualShaderNodeFloatParameter>(node.ptr());
4602
if (float_parameter.is_valid()) {
4603
_replace_node(type_id, node_id, "VisualShaderNodeFloatParameter", "VisualShaderNodeFloatConstant");
4604
var = float_parameter->get_default_value();
4605
caught = true;
4606
}
4607
}
4608
4609
// int
4610
if (!caught) {
4611
if (!p_vice_versa) {
4612
Ref<VisualShaderNodeIntConstant> int_const = Object::cast_to<VisualShaderNodeIntConstant>(node.ptr());
4613
if (int_const.is_valid()) {
4614
_replace_node(type_id, node_id, "VisualShaderNodeIntConstant", "VisualShaderNodeIntParameter");
4615
var = int_const->get_constant();
4616
caught = true;
4617
}
4618
} else {
4619
Ref<VisualShaderNodeIntParameter> int_parameter = Object::cast_to<VisualShaderNodeIntParameter>(node.ptr());
4620
if (int_parameter.is_valid()) {
4621
_replace_node(type_id, node_id, "VisualShaderNodeIntParameter", "VisualShaderNodeIntConstant");
4622
var = int_parameter->get_default_value();
4623
caught = true;
4624
}
4625
}
4626
}
4627
4628
// boolean
4629
if (!caught) {
4630
if (!p_vice_versa) {
4631
Ref<VisualShaderNodeBooleanConstant> boolean_const = Object::cast_to<VisualShaderNodeBooleanConstant>(node.ptr());
4632
if (boolean_const.is_valid()) {
4633
_replace_node(type_id, node_id, "VisualShaderNodeBooleanConstant", "VisualShaderNodeBooleanParameter");
4634
var = boolean_const->get_constant();
4635
caught = true;
4636
}
4637
} else {
4638
Ref<VisualShaderNodeBooleanParameter> boolean_parameter = Object::cast_to<VisualShaderNodeBooleanParameter>(node.ptr());
4639
if (boolean_parameter.is_valid()) {
4640
_replace_node(type_id, node_id, "VisualShaderNodeBooleanParameter", "VisualShaderNodeBooleanConstant");
4641
var = boolean_parameter->get_default_value();
4642
caught = true;
4643
}
4644
}
4645
}
4646
4647
// vec2
4648
if (!caught) {
4649
if (!p_vice_versa) {
4650
Ref<VisualShaderNodeVec2Constant> vec2_const = Object::cast_to<VisualShaderNodeVec2Constant>(node.ptr());
4651
if (vec2_const.is_valid()) {
4652
_replace_node(type_id, node_id, "VisualShaderNodeVec2Constant", "VisualShaderNodeVec2Parameter");
4653
var = vec2_const->get_constant();
4654
caught = true;
4655
}
4656
} else {
4657
Ref<VisualShaderNodeVec2Parameter> vec2_parameter = Object::cast_to<VisualShaderNodeVec2Parameter>(node.ptr());
4658
if (vec2_parameter.is_valid()) {
4659
_replace_node(type_id, node_id, "VisualShaderNodeVec2Parameter", "VisualShaderNodeVec2Constant");
4660
var = vec2_parameter->get_default_value();
4661
caught = true;
4662
}
4663
}
4664
}
4665
4666
// vec3
4667
if (!caught) {
4668
if (!p_vice_versa) {
4669
Ref<VisualShaderNodeVec3Constant> vec3_const = Object::cast_to<VisualShaderNodeVec3Constant>(node.ptr());
4670
if (vec3_const.is_valid()) {
4671
_replace_node(type_id, node_id, "VisualShaderNodeVec3Constant", "VisualShaderNodeVec3Parameter");
4672
var = vec3_const->get_constant();
4673
caught = true;
4674
}
4675
} else {
4676
Ref<VisualShaderNodeVec3Parameter> vec3_parameter = Object::cast_to<VisualShaderNodeVec3Parameter>(node.ptr());
4677
if (vec3_parameter.is_valid()) {
4678
_replace_node(type_id, node_id, "VisualShaderNodeVec3Parameter", "VisualShaderNodeVec3Constant");
4679
var = vec3_parameter->get_default_value();
4680
caught = true;
4681
}
4682
}
4683
}
4684
4685
// vec4
4686
if (!caught) {
4687
if (!p_vice_versa) {
4688
Ref<VisualShaderNodeVec4Constant> vec4_const = Object::cast_to<VisualShaderNodeVec4Constant>(node.ptr());
4689
if (vec4_const.is_valid()) {
4690
_replace_node(type_id, node_id, "VisualShaderNodeVec4Constant", "VisualShaderNodeVec4Parameter");
4691
var = vec4_const->get_constant();
4692
caught = true;
4693
}
4694
} else {
4695
Ref<VisualShaderNodeVec4Parameter> vec4_parameter = Object::cast_to<VisualShaderNodeVec4Parameter>(node.ptr());
4696
if (vec4_parameter.is_valid()) {
4697
_replace_node(type_id, node_id, "VisualShaderNodeVec4Parameter", "VisualShaderNodeVec4Constant");
4698
var = vec4_parameter->get_default_value();
4699
caught = true;
4700
}
4701
}
4702
}
4703
4704
// color
4705
if (!caught) {
4706
if (!p_vice_versa) {
4707
Ref<VisualShaderNodeColorConstant> color_const = Object::cast_to<VisualShaderNodeColorConstant>(node.ptr());
4708
if (color_const.is_valid()) {
4709
_replace_node(type_id, node_id, "VisualShaderNodeColorConstant", "VisualShaderNodeColorParameter");
4710
var = color_const->get_constant();
4711
caught = true;
4712
}
4713
} else {
4714
Ref<VisualShaderNodeColorParameter> color_parameter = Object::cast_to<VisualShaderNodeColorParameter>(node.ptr());
4715
if (color_parameter.is_valid()) {
4716
_replace_node(type_id, node_id, "VisualShaderNodeColorParameter", "VisualShaderNodeColorConstant");
4717
var = color_parameter->get_default_value();
4718
caught = true;
4719
}
4720
}
4721
}
4722
4723
// transform
4724
if (!caught) {
4725
if (!p_vice_versa) {
4726
Ref<VisualShaderNodeTransformConstant> transform_const = Object::cast_to<VisualShaderNodeTransformConstant>(node.ptr());
4727
if (transform_const.is_valid()) {
4728
_replace_node(type_id, node_id, "VisualShaderNodeTransformConstant", "VisualShaderNodeTransformParameter");
4729
var = transform_const->get_constant();
4730
caught = true;
4731
}
4732
} else {
4733
Ref<VisualShaderNodeTransformParameter> transform_parameter = Object::cast_to<VisualShaderNodeTransformParameter>(node.ptr());
4734
if (transform_parameter.is_valid()) {
4735
_replace_node(type_id, node_id, "VisualShaderNodeTransformParameter", "VisualShaderNodeTransformConstant");
4736
var = transform_parameter->get_default_value();
4737
caught = true;
4738
}
4739
}
4740
}
4741
ERR_CONTINUE(!caught);
4742
int preview_port = node->get_output_port_for_preview();
4743
4744
if (!p_vice_versa) {
4745
undo_redo->add_do_method(this, "_update_parameter", type_id, node_id, var, preview_port);
4746
undo_redo->add_undo_method(this, "_update_constant", type_id, node_id, var, preview_port);
4747
} else {
4748
undo_redo->add_do_method(this, "_update_constant", type_id, node_id, var, preview_port);
4749
undo_redo->add_undo_method(this, "_update_parameter", type_id, node_id, var, preview_port);
4750
4751
Ref<VisualShaderNodeParameter> parameter = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4752
ERR_CONTINUE(parameter.is_null());
4753
4754
deleted_names.insert(parameter->get_parameter_name());
4755
}
4756
4757
undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, node_id);
4758
undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, node_id);
4759
}
4760
4761
undo_redo->add_do_method(this, "_update_parameters", true);
4762
undo_redo->add_undo_method(this, "_update_parameters", true);
4763
4764
if (deleted_names.size() > 0) {
4765
_update_parameter_refs(deleted_names);
4766
}
4767
4768
undo_redo->commit_action();
4769
}
4770
4771
void VisualShaderEditor::_detach_nodes_from_frame(int p_type, const List<int> &p_nodes) {
4772
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4773
for (int node_id : p_nodes) {
4774
Ref<VisualShaderNode> node = visual_shader->get_node((VisualShader::Type)p_type, node_id);
4775
if (node.is_null()) {
4776
continue;
4777
}
4778
int frame_id = node->get_frame();
4779
if (frame_id != -1) {
4780
undo_redo->add_do_method(graph_plugin.ptr(), "detach_node_from_frame", p_type, node_id);
4781
undo_redo->add_do_method(visual_shader.ptr(), "detach_node_from_frame", p_type, node_id);
4782
undo_redo->add_undo_method(visual_shader.ptr(), "attach_node_to_frame", p_type, node_id, frame_id);
4783
undo_redo->add_undo_method(graph_plugin.ptr(), "attach_node_to_frame", p_type, node_id, frame_id);
4784
}
4785
}
4786
}
4787
4788
void VisualShaderEditor::_detach_nodes_from_frame_request() {
4789
// Called from context menu.
4790
List<int> to_detach_node_ids;
4791
for (int i = 0; i < graph->get_child_count(); i++) {
4792
GraphElement *gn = Object::cast_to<GraphElement>(graph->get_child(i));
4793
if (gn) {
4794
int id = String(gn->get_name()).to_int();
4795
if (gn->is_selected()) {
4796
to_detach_node_ids.push_back(id);
4797
}
4798
}
4799
}
4800
if (to_detach_node_ids.is_empty()) {
4801
return;
4802
}
4803
4804
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4805
undo_redo->create_action(TTR("Detach VisualShader Node(s) from Frame"));
4806
_detach_nodes_from_frame(get_current_shader_type(), to_detach_node_ids);
4807
undo_redo->commit_action();
4808
}
4809
4810
void VisualShaderEditor::_delete_node_request(int p_type, int p_node) {
4811
Ref<VisualShaderNode> node = visual_shader->get_node((VisualShader::Type)p_type, p_node);
4812
if (!node->is_deletable()) {
4813
return;
4814
}
4815
4816
List<int> to_erase;
4817
to_erase.push_back(p_node);
4818
4819
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4820
undo_redo->create_action(TTR("Delete VisualShader Node"));
4821
_delete_nodes(p_type, to_erase);
4822
undo_redo->commit_action();
4823
}
4824
4825
void VisualShaderEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) {
4826
List<int> to_erase;
4827
4828
if (p_nodes.is_empty()) {
4829
// Called from context menu.
4830
for (int i = 0; i < graph->get_child_count(); i++) {
4831
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
4832
if (!graph_element) {
4833
continue;
4834
}
4835
4836
VisualShader::Type type = get_current_shader_type();
4837
int id = String(graph_element->get_name()).to_int();
4838
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4839
if (vsnode->is_deletable() && graph_element->is_selected()) {
4840
to_erase.push_back(graph_element->get_name().operator String().to_int());
4841
}
4842
}
4843
} else {
4844
VisualShader::Type type = get_current_shader_type();
4845
for (int i = 0; i < p_nodes.size(); i++) {
4846
int id = p_nodes[i].operator String().to_int();
4847
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4848
if (vsnode->is_deletable()) {
4849
to_erase.push_back(id);
4850
}
4851
}
4852
}
4853
4854
if (to_erase.is_empty()) {
4855
return;
4856
}
4857
4858
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
4859
undo_redo->create_action(TTR("Delete VisualShader Node(s)"));
4860
_delete_nodes(get_current_shader_type(), to_erase);
4861
undo_redo->commit_action();
4862
}
4863
4864
void VisualShaderEditor::_node_selected(Object *p_node) {
4865
VisualShader::Type type = get_current_shader_type();
4866
4867
GraphElement *graph_element = Object::cast_to<GraphElement>(p_node);
4868
ERR_FAIL_NULL(graph_element);
4869
4870
int id = String(graph_element->get_name()).to_int();
4871
4872
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4873
ERR_FAIL_COND(vsnode.is_null());
4874
}
4875
4876
void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
4877
Ref<InputEventMouseMotion> mm = p_event;
4878
Ref<InputEventMouseButton> mb = p_event;
4879
VisualShader::Type type = get_current_shader_type();
4880
4881
// Highlight valid connection on which a node can be dropped.
4882
if (mm.is_valid() && mm->get_button_mask().has_flag(MouseButtonMask::LEFT)) {
4883
Ref<GraphEdit::Connection> closest_connection;
4884
graph->reset_all_connection_activity();
4885
if (_check_node_drop_on_connection(graph->get_local_mouse_position(), &closest_connection)) {
4886
graph->set_connection_activity(closest_connection->from_node, closest_connection->from_port, closest_connection->to_node, closest_connection->to_port, 1.0);
4887
}
4888
}
4889
4890
Ref<VisualShaderNode> selected_vsnode;
4891
// Right click actions.
4892
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) {
4893
selected_constants.clear();
4894
selected_parameters.clear();
4895
selected_frame = -1;
4896
selected_float_constant = -1;
4897
4898
List<int> selected_deletable_graph_elements;
4899
List<GraphElement *> selected_graph_elements;
4900
for (int i = 0; i < graph->get_child_count(); i++) {
4901
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
4902
if (!graph_element) {
4903
continue;
4904
}
4905
int id = String(graph_element->get_name()).to_int();
4906
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
4907
4908
if (!graph_element->is_selected()) {
4909
continue;
4910
}
4911
4912
selected_graph_elements.push_back(graph_element);
4913
4914
if (!vsnode->is_deletable()) {
4915
continue;
4916
}
4917
4918
selected_deletable_graph_elements.push_back(id);
4919
4920
Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
4921
selected_vsnode = node;
4922
4923
VisualShaderNodeFrame *frame_node = Object::cast_to<VisualShaderNodeFrame>(node.ptr());
4924
if (frame_node != nullptr) {
4925
selected_frame = id;
4926
}
4927
VisualShaderNodeConstant *constant_node = Object::cast_to<VisualShaderNodeConstant>(node.ptr());
4928
if (constant_node != nullptr) {
4929
selected_constants.insert(id);
4930
}
4931
VisualShaderNodeFloatConstant *float_constant_node = Object::cast_to<VisualShaderNodeFloatConstant>(node.ptr());
4932
if (float_constant_node != nullptr) {
4933
selected_float_constant = id;
4934
}
4935
VisualShaderNodeParameter *parameter_node = Object::cast_to<VisualShaderNodeParameter>(node.ptr());
4936
if (parameter_node != nullptr && parameter_node->is_convertible_to_constant()) {
4937
selected_parameters.insert(id);
4938
}
4939
}
4940
4941
if (selected_deletable_graph_elements.size() > 1) {
4942
selected_frame = -1;
4943
selected_float_constant = -1;
4944
}
4945
4946
bool copy_buffer_empty = true;
4947
for (const CopyItem &item : copy_items_buffer) {
4948
if (!item.disabled) {
4949
copy_buffer_empty = false;
4950
break;
4951
}
4952
}
4953
4954
menu_point = graph->get_local_mouse_position();
4955
Point2 gpos = get_screen_position() + get_local_mouse_position();
4956
4957
Ref<GraphEdit::Connection> closest_connection = graph->get_closest_connection_at_point(menu_point);
4958
if (closest_connection.is_valid()) {
4959
clicked_connection = closest_connection;
4960
saved_node_pos = graph->get_local_mouse_position();
4961
saved_node_pos_dirty = true;
4962
connection_popup_menu->set_position(gpos);
4963
connection_popup_menu->reset_size();
4964
connection_popup_menu->popup();
4965
} else if (selected_graph_elements.is_empty() && copy_buffer_empty) {
4966
_show_members_dialog(true);
4967
} else {
4968
popup_menu->set_item_disabled(NodeMenuOptions::CUT, selected_deletable_graph_elements.is_empty());
4969
popup_menu->set_item_disabled(NodeMenuOptions::COPY, selected_deletable_graph_elements.is_empty());
4970
popup_menu->set_item_disabled(NodeMenuOptions::PASTE, copy_buffer_empty);
4971
popup_menu->set_item_disabled(NodeMenuOptions::DELETE_, selected_deletable_graph_elements.is_empty());
4972
popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, selected_deletable_graph_elements.is_empty());
4973
popup_menu->set_item_disabled(NodeMenuOptions::CLEAR_COPY_BUFFER, copy_buffer_empty);
4974
4975
int temp = popup_menu->get_item_index(NodeMenuOptions::SEPARATOR2);
4976
if (temp != -1) {
4977
popup_menu->remove_item(temp);
4978
}
4979
temp = popup_menu->get_item_index(NodeMenuOptions::FLOAT_CONSTANTS);
4980
if (temp != -1) {
4981
popup_menu->remove_item(temp);
4982
}
4983
temp = popup_menu->get_item_index(NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS);
4984
if (temp != -1) {
4985
popup_menu->remove_item(temp);
4986
}
4987
temp = popup_menu->get_item_index(NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS);
4988
if (temp != -1) {
4989
popup_menu->remove_item(temp);
4990
}
4991
temp = popup_menu->get_item_index(NodeMenuOptions::SEPARATOR3);
4992
if (temp != -1) {
4993
popup_menu->remove_item(temp);
4994
}
4995
temp = popup_menu->get_item_index(NodeMenuOptions::UNLINK_FROM_PARENT_FRAME);
4996
if (temp != -1) {
4997
popup_menu->remove_item(temp);
4998
}
4999
temp = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_TITLE);
5000
if (temp != -1) {
5001
popup_menu->remove_item(temp);
5002
}
5003
temp = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
5004
if (temp != -1) {
5005
popup_menu->remove_item(temp);
5006
}
5007
temp = popup_menu->get_item_index(NodeMenuOptions::SET_FRAME_COLOR);
5008
if (temp != -1) {
5009
popup_menu->remove_item(temp);
5010
}
5011
temp = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5012
if (temp != -1) {
5013
popup_menu->remove_item(temp);
5014
}
5015
5016
if (selected_constants.size() > 0 || selected_parameters.size() > 0) {
5017
popup_menu->add_separator("", NodeMenuOptions::SEPARATOR2);
5018
5019
if (selected_float_constant != -1) {
5020
if (!constants_submenu) {
5021
constants_submenu = memnew(PopupMenu);
5022
5023
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
5024
constants_submenu->add_item(float_constant_defs[i].name, i);
5025
}
5026
constants_submenu->connect("index_pressed", callable_mp(this, &VisualShaderEditor::_float_constant_selected));
5027
}
5028
popup_menu->add_submenu_node_item(TTR("Float Constants"), constants_submenu, int(NodeMenuOptions::FLOAT_CONSTANTS));
5029
}
5030
5031
if (selected_constants.size() > 0) {
5032
popup_menu->add_item(TTR("Convert Constant(s) to Parameter(s)"), NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS);
5033
}
5034
5035
if (selected_parameters.size() > 0) {
5036
popup_menu->add_item(TTR("Convert Parameter(s) to Constant(s)"), NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS);
5037
}
5038
}
5039
5040
// Check if any selected node is attached to a frame.
5041
bool is_attached_to_frame = false;
5042
for (GraphElement *graph_element : selected_graph_elements) {
5043
if (graph->get_element_frame(graph_element->get_name())) {
5044
is_attached_to_frame = true;
5045
break;
5046
}
5047
}
5048
5049
if (is_attached_to_frame) {
5050
popup_menu->add_item(TTR("Detach from Parent Frame"), NodeMenuOptions::UNLINK_FROM_PARENT_FRAME);
5051
}
5052
5053
if (selected_frame != -1) {
5054
popup_menu->add_separator("", NodeMenuOptions::SEPARATOR3);
5055
popup_menu->add_item(TTR("Set Frame Title"), NodeMenuOptions::SET_FRAME_TITLE);
5056
popup_menu->add_check_item(TTR("Enable Auto Shrink"), NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5057
popup_menu->add_check_item(TTR("Enable Tint Color"), NodeMenuOptions::ENABLE_FRAME_COLOR);
5058
5059
VisualShaderNodeFrame *frame_ref = Object::cast_to<VisualShaderNodeFrame>(selected_vsnode.ptr());
5060
if (frame_ref) {
5061
int item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_COLOR);
5062
popup_menu->set_item_checked(item_index, frame_ref->is_tint_color_enabled());
5063
if (frame_ref->is_tint_color_enabled()) {
5064
popup_menu->add_item(TTR("Set Tint Color"), NodeMenuOptions::SET_FRAME_COLOR);
5065
}
5066
5067
item_index = popup_menu->get_item_index(NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK);
5068
popup_menu->set_item_checked(item_index, frame_ref->is_autoshrink_enabled());
5069
}
5070
}
5071
5072
popup_menu->set_position(gpos);
5073
popup_menu->reset_size();
5074
popup_menu->popup();
5075
}
5076
}
5077
}
5078
5079
void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type, VisualShaderNode::PortType p_output_port_type) {
5080
if (members_input_port_type != p_input_port_type || members_output_port_type != p_output_port_type) {
5081
members_input_port_type = p_input_port_type;
5082
members_output_port_type = p_output_port_type;
5083
_update_options_menu();
5084
}
5085
5086
if (at_mouse_pos) {
5087
saved_node_pos_dirty = true;
5088
saved_node_pos = graph->get_local_mouse_position();
5089
5090
Point2 gpos = get_screen_position() + get_local_mouse_position();
5091
members_dialog->set_position(gpos);
5092
} else {
5093
saved_node_pos_dirty = false;
5094
members_dialog->set_position(graph->get_screen_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5095
}
5096
5097
if (members_dialog->is_visible()) {
5098
members_dialog->grab_focus();
5099
return;
5100
}
5101
5102
members_dialog->popup();
5103
5104
// Keep dialog within window bounds.
5105
Rect2 window_rect = Rect2(get_window()->get_position(), get_window()->get_size());
5106
Rect2 dialog_rect = Rect2(members_dialog->get_position(), members_dialog->get_size());
5107
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5108
members_dialog->set_position(members_dialog->get_position() - difference);
5109
5110
node_filter->grab_focus();
5111
node_filter->select_all();
5112
}
5113
5114
void VisualShaderEditor::_varying_menu_id_pressed(int p_idx) {
5115
switch (VaryingMenuOptions(p_idx)) {
5116
case VaryingMenuOptions::ADD: {
5117
_show_add_varying_dialog();
5118
} break;
5119
case VaryingMenuOptions::REMOVE: {
5120
_show_remove_varying_dialog();
5121
} break;
5122
default:
5123
break;
5124
}
5125
}
5126
5127
void VisualShaderEditor::_show_add_varying_dialog() {
5128
_varying_name_changed(varying_name->get_text());
5129
5130
add_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5131
add_varying_dialog->popup();
5132
5133
varying_name->grab_focus();
5134
5135
// Keep dialog within window bounds.
5136
Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
5137
Rect2 dialog_rect = Rect2(add_varying_dialog->get_position(), add_varying_dialog->get_size());
5138
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5139
add_varying_dialog->set_position(add_varying_dialog->get_position() - difference);
5140
}
5141
5142
void VisualShaderEditor::_show_remove_varying_dialog() {
5143
remove_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
5144
remove_varying_dialog->popup();
5145
5146
varyings->grab_focus();
5147
5148
// Keep dialog within window bounds.
5149
Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
5150
Rect2 dialog_rect = Rect2(remove_varying_dialog->get_position(), remove_varying_dialog->get_size());
5151
Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).maxf(0);
5152
remove_varying_dialog->set_position(remove_varying_dialog->get_position() - difference);
5153
}
5154
5155
void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_event) {
5156
// Redirect navigational key events to the tree.
5157
Ref<InputEventKey> key = p_event;
5158
if (key.is_valid()) {
5159
if (key->is_action("ui_up", true) || key->is_action("ui_down", true) || key->is_action("ui_page_up") || key->is_action("ui_page_down")) {
5160
members->gui_input(key);
5161
node_filter->accept_event();
5162
}
5163
}
5164
}
5165
5166
void VisualShaderEditor::_param_filter_changed(const String &p_text) {
5167
param_filter_name = p_text;
5168
5169
if (!_update_preview_parameter_tree()) {
5170
_clear_preview_param();
5171
}
5172
}
5173
5174
void VisualShaderEditor::_param_property_changed(const String &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
5175
if (p_changing) {
5176
return;
5177
}
5178
String raw_prop_name = p_property.trim_prefix("shader_parameter/");
5179
5180
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5181
5182
undo_redo->create_action(vformat(TTR("Edit Preview Parameter: %s"), p_property));
5183
undo_redo->add_do_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, p_value);
5184
undo_redo->add_undo_method(visual_shader.ptr(), "_set_preview_shader_parameter", raw_prop_name, preview_material->get(p_property));
5185
undo_redo->add_do_method(this, "_update_current_param");
5186
undo_redo->add_undo_method(this, "_update_current_param");
5187
undo_redo->commit_action();
5188
}
5189
5190
void VisualShaderEditor::_update_current_param() {
5191
if (current_prop != nullptr) {
5192
String name = current_prop->get_meta("id");
5193
if (visual_shader->_has_preview_shader_parameter(name)) {
5194
preview_material->set("shader_parameter/" + name, visual_shader->_get_preview_shader_parameter(name));
5195
} else {
5196
preview_material->set("shader_parameter/" + name, Variant());
5197
}
5198
current_prop->update_property();
5199
current_prop->update_editor_property_status();
5200
current_prop->update_cache();
5201
}
5202
}
5203
5204
void VisualShaderEditor::_param_selected() {
5205
_clear_preview_param();
5206
5207
TreeItem *item = parameters->get_selected();
5208
selected_param_id = item->get_meta("id");
5209
5210
PropertyInfo pi = parameter_props.get(selected_param_id);
5211
EditorProperty *prop = EditorInspector::instantiate_property_editor(preview_material.ptr(), pi.type, pi.name, pi.hint, pi.hint_string, pi.usage);
5212
if (!prop) {
5213
return;
5214
}
5215
prop->connect("property_changed", callable_mp(this, &VisualShaderEditor::_param_property_changed));
5216
prop->set_h_size_flags(SIZE_EXPAND_FILL);
5217
prop->set_object_and_property(preview_material.ptr(), "shader_parameter/" + pi.name);
5218
5219
prop->set_label(TTR("Value:"));
5220
prop->update_property();
5221
prop->update_editor_property_status();
5222
prop->update_cache();
5223
5224
current_prop = prop;
5225
current_prop->set_meta("id", selected_param_id);
5226
5227
param_vbox2->add_child(prop);
5228
param_vbox->show();
5229
}
5230
5231
void VisualShaderEditor::_param_unselected() {
5232
parameters->deselect_all();
5233
5234
_clear_preview_param();
5235
}
5236
5237
void VisualShaderEditor::_help_open() {
5238
OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/visual_shaders.html", GODOT_VERSION_DOCS_URL));
5239
}
5240
5241
void VisualShaderEditor::_notification(int p_what) {
5242
switch (p_what) {
5243
case NOTIFICATION_POSTINITIALIZE: {
5244
_update_options_menu();
5245
} break;
5246
5247
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
5248
if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/panning")) {
5249
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")));
5250
graph->set_warped_panning(EDITOR_GET("editors/panning/warped_mouse_panning"));
5251
}
5252
if (EditorSettings::get_singleton()->check_changed_settings_in_group("editors/visual_editors")) {
5253
graph->set_minimap_opacity(EDITOR_GET("editors/visual_editors/minimap_opacity"));
5254
graph->set_grid_pattern((GraphEdit::GridPattern) int(EDITOR_GET("editors/visual_editors/grid_pattern")));
5255
graph->set_connection_lines_curvature(EDITOR_GET("editors/visual_editors/lines_curvature"));
5256
5257
_update_graph();
5258
}
5259
} break;
5260
5261
case NOTIFICATION_ENTER_TREE: {
5262
node_filter->set_clear_button_enabled(true);
5263
5264
// collapse tree by default
5265
5266
TreeItem *category = members->get_root()->get_first_child();
5267
while (category) {
5268
category->set_collapsed(true);
5269
TreeItem *sub_category = category->get_first_child();
5270
while (sub_category) {
5271
sub_category->set_collapsed(true);
5272
sub_category = sub_category->get_next();
5273
}
5274
category = category->get_next();
5275
}
5276
5277
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")));
5278
graph->set_warped_panning(EDITOR_GET("editors/panning/warped_mouse_panning"));
5279
} break;
5280
5281
case NOTIFICATION_THEME_CHANGED: {
5282
site_search->set_button_icon(get_editor_theme_icon(SNAME("ExternalLink")));
5283
highend_label->set_modulate(get_theme_color(SNAME("highend_color"), EditorStringName(Editor)));
5284
5285
param_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search")));
5286
node_filter->set_right_icon(Control::get_editor_theme_icon(SNAME("Search")));
5287
5288
code_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("Shader")));
5289
shader_preview_button->set_button_icon(Control::get_editor_theme_icon(SNAME("SubViewport")));
5290
5291
{
5292
Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
5293
Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
5294
Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color");
5295
Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color");
5296
Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
5297
Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
5298
Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
5299
Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
5300
Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
5301
Color error_color = get_theme_color(SNAME("error_color"), EditorStringName(Editor));
5302
5303
preview_text->add_theme_color_override("background_color", background_color);
5304
varying_error_label->add_theme_color_override(SceneStringName(font_color), error_color);
5305
5306
for (const String &E : keyword_list) {
5307
if (ShaderLanguage::is_control_flow_keyword(E)) {
5308
syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
5309
} else {
5310
syntax_highlighter->add_keyword_color(E, keyword_color);
5311
}
5312
}
5313
5314
preview_text->begin_bulk_theme_override();
5315
preview_text->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)));
5316
preview_text->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size(SNAME("expression_size"), EditorStringName(EditorFonts)));
5317
preview_text->add_theme_color_override(SceneStringName(font_color), text_color);
5318
preview_text->end_bulk_theme_override();
5319
5320
syntax_highlighter->set_number_color(number_color);
5321
syntax_highlighter->set_symbol_color(symbol_color);
5322
syntax_highlighter->set_function_color(function_color);
5323
syntax_highlighter->set_member_variable_color(members_color);
5324
syntax_highlighter->clear_color_regions();
5325
syntax_highlighter->add_color_region("/*", "*/", comment_color, false);
5326
syntax_highlighter->add_color_region("//", "", comment_color, true);
5327
5328
preview_text->clear_comment_delimiters();
5329
preview_text->add_comment_delimiter("/*", "*/", false);
5330
preview_text->add_comment_delimiter("//", "", true);
5331
5332
error_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Panel")));
5333
error_label->begin_bulk_theme_override();
5334
error_label->add_theme_font_override(SceneStringName(font), get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts)));
5335
error_label->add_theme_font_size_override(SceneStringName(font_size), get_theme_font_size(SNAME("status_source_size"), EditorStringName(EditorFonts)));
5336
error_label->add_theme_color_override(SceneStringName(font_color), error_color);
5337
error_label->end_bulk_theme_override();
5338
}
5339
5340
tools->set_button_icon(get_editor_theme_icon(SNAME("Tools")));
5341
preview_tools->set_button_icon(get_editor_theme_icon(SNAME("Tools")));
5342
5343
if (is_visible_in_tree()) {
5344
_update_graph();
5345
}
5346
update_toggle_files_button();
5347
} break;
5348
5349
case NOTIFICATION_VISIBILITY_CHANGED: {
5350
update_toggle_files_button();
5351
} break;
5352
5353
case NOTIFICATION_DRAG_BEGIN: {
5354
Dictionary dd = get_viewport()->gui_get_drag_data();
5355
if (members->is_visible_in_tree() && dd.has("id")) {
5356
members->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
5357
}
5358
} break;
5359
5360
case NOTIFICATION_DRAG_END: {
5361
members->set_drop_mode_flags(0);
5362
} break;
5363
}
5364
}
5365
5366
void VisualShaderEditor::_scroll_offset_changed(const Vector2 &p_scroll) {
5367
if (!shader_fully_loaded) {
5368
return;
5369
}
5370
5371
panning_debounce_timer->start();
5372
}
5373
5374
void VisualShaderEditor::_node_changed(int p_id) {
5375
if (is_visible_in_tree()) {
5376
_update_graph();
5377
}
5378
}
5379
5380
void VisualShaderEditor::_nodes_linked_to_frame_request(const TypedArray<StringName> &p_nodes, const StringName &p_frame) {
5381
Vector<int> node_ids;
5382
for (int i = 0; i < p_nodes.size(); i++) {
5383
node_ids.push_back(p_nodes[i].operator String().to_int());
5384
}
5385
frame_node_id_to_link_to = p_frame.operator String().to_int();
5386
nodes_link_to_frame_buffer = node_ids;
5387
}
5388
5389
void VisualShaderEditor::_frame_rect_changed(const GraphFrame *p_frame, const Rect2 &p_new_rect) {
5390
if (p_frame == nullptr) {
5391
return;
5392
}
5393
5394
int node_id = String(p_frame->get_name()).to_int();
5395
Ref<VisualShaderNodeResizableBase> vsnode = visual_shader->get_node(get_current_shader_type(), node_id);
5396
if (vsnode.is_null()) {
5397
return;
5398
}
5399
vsnode->set_size(p_new_rect.size / graph->get_zoom());
5400
}
5401
5402
void VisualShaderEditor::_dup_copy_nodes(int p_type, List<CopyItem> &r_items, List<VisualShader::Connection> &r_connections) {
5403
VisualShader::Type type = (VisualShader::Type)p_type;
5404
5405
selection_center.x = 0.0f;
5406
selection_center.y = 0.0f;
5407
5408
HashSet<int> nodes;
5409
5410
for (int i = 0; i < graph->get_child_count(); i++) {
5411
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
5412
if (graph_element) {
5413
int id = String(graph_element->get_name()).to_int();
5414
5415
Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
5416
Ref<VisualShaderNodeOutput> output = node;
5417
if (output.is_valid()) { // can't duplicate output
5418
continue;
5419
}
5420
5421
if (node.is_valid() && graph_element->is_selected()) {
5422
Vector2 pos = visual_shader->get_node_position(type, id);
5423
selection_center += pos;
5424
5425
CopyItem item;
5426
item.id = id;
5427
item.node = visual_shader->get_node(type, id)->duplicate();
5428
item.position = visual_shader->get_node_position(type, id);
5429
5430
Ref<VisualShaderNodeResizableBase> resizable_base = node;
5431
if (resizable_base.is_valid()) {
5432
item.size = resizable_base->get_size();
5433
}
5434
5435
Ref<VisualShaderNodeGroupBase> group = node;
5436
if (group.is_valid()) {
5437
item.group_inputs = group->get_inputs();
5438
item.group_outputs = group->get_outputs();
5439
}
5440
5441
Ref<VisualShaderNodeExpression> expression = node;
5442
if (expression.is_valid()) {
5443
item.expression = expression->get_expression();
5444
}
5445
5446
r_items.push_back(item);
5447
5448
nodes.insert(id);
5449
}
5450
}
5451
}
5452
5453
List<VisualShader::Connection> node_connections;
5454
visual_shader->get_node_connections(type, &node_connections);
5455
5456
for (const VisualShader::Connection &E : node_connections) {
5457
if (nodes.has(E.from_node) && nodes.has(E.to_node)) {
5458
r_connections.push_back(E);
5459
}
5460
}
5461
5462
selection_center /= (float)r_items.size();
5463
}
5464
5465
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) {
5466
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5467
if (p_duplicate) {
5468
undo_redo->create_action(TTR("Duplicate VisualShader Node(s)"));
5469
} else {
5470
bool copy_buffer_empty = true;
5471
for (const CopyItem &item : copy_items_buffer) {
5472
if (!item.disabled) {
5473
copy_buffer_empty = false;
5474
break;
5475
}
5476
}
5477
if (copy_buffer_empty) {
5478
return;
5479
}
5480
5481
undo_redo->create_action(TTR("Paste VisualShader Node(s)"));
5482
}
5483
5484
VisualShader::Type type = (VisualShader::Type)p_type;
5485
5486
int base_id = visual_shader->get_valid_node_id(type);
5487
int id_from = base_id;
5488
HashMap<int, int> connection_remap; // Used for connections and frame attachments.
5489
HashSet<int> unsupported_set;
5490
HashSet<int> added_set;
5491
5492
for (CopyItem &item : r_items) {
5493
if (item.disabled) {
5494
unsupported_set.insert(item.id);
5495
continue;
5496
}
5497
connection_remap[item.id] = id_from;
5498
Ref<VisualShaderNode> node = item.node->duplicate();
5499
node->set_frame(-1); // Do not reattach nodes to frame (for now).
5500
5501
Ref<VisualShaderNodeResizableBase> resizable_base = Object::cast_to<VisualShaderNodeResizableBase>(node.ptr());
5502
if (resizable_base.is_valid()) {
5503
undo_redo->add_do_method(node.ptr(), "set_size", item.size);
5504
}
5505
5506
Ref<VisualShaderNodeFrame> frame = Object::cast_to<VisualShaderNodeFrame>(node.ptr());
5507
if (frame.is_valid()) {
5508
// Do not reattach nodes to frame (for now).
5509
undo_redo->add_do_method(node.ptr(), "set_attached_nodes", PackedInt32Array());
5510
}
5511
5512
Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr());
5513
if (group.is_valid()) {
5514
undo_redo->add_do_method(node.ptr(), "set_inputs", item.group_inputs);
5515
undo_redo->add_do_method(node.ptr(), "set_outputs", item.group_outputs);
5516
}
5517
5518
Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(node.ptr());
5519
if (expression.is_valid()) {
5520
undo_redo->add_do_method(node.ptr(), "set_expression", item.expression);
5521
}
5522
5523
undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, node, item.position + p_offset, id_from);
5524
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from, false, false);
5525
5526
added_set.insert(id_from);
5527
id_from++;
5528
}
5529
5530
// Attach nodes to frame.
5531
for (const CopyItem &item : r_items) {
5532
Ref<VisualShaderNode> node = item.node;
5533
if (node->get_frame() == -1) {
5534
continue;
5535
}
5536
5537
int new_node_id = connection_remap[item.id];
5538
int new_frame_id = node->get_frame();
5539
undo_redo->add_do_method(visual_shader.ptr(), "attach_node_to_frame", type, new_node_id, new_frame_id);
5540
undo_redo->add_do_method(graph_plugin.ptr(), "attach_node_to_frame", type, new_node_id, new_frame_id);
5541
}
5542
5543
// Connect nodes.
5544
for (const VisualShader::Connection &E : p_connections) {
5545
if (unsupported_set.has(E.from_node) || unsupported_set.has(E.to_node)) {
5546
continue;
5547
}
5548
5549
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);
5550
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);
5551
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);
5552
}
5553
5554
id_from = base_id;
5555
for (const CopyItem &item : r_items) {
5556
if (item.disabled) {
5557
continue;
5558
}
5559
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
5560
undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from, false);
5561
id_from++;
5562
}
5563
5564
undo_redo->commit_action();
5565
5566
// Reselect nodes by excluding the other ones.
5567
for (int i = 0; i < graph->get_child_count(); i++) {
5568
GraphElement *graph_element = Object::cast_to<GraphElement>(graph->get_child(i));
5569
if (graph_element) {
5570
int id = String(graph_element->get_name()).to_int();
5571
if (added_set.has(id)) {
5572
graph_element->set_selected(true);
5573
} else {
5574
graph_element->set_selected(false);
5575
}
5576
}
5577
}
5578
}
5579
5580
void VisualShaderEditor::_clear_copy_buffer() {
5581
copy_items_buffer.clear();
5582
copy_connections_buffer.clear();
5583
}
5584
5585
void VisualShaderEditor::_duplicate_nodes() {
5586
int type = get_current_shader_type();
5587
5588
List<CopyItem> items;
5589
List<VisualShader::Connection> node_connections;
5590
5591
_dup_copy_nodes(type, items, node_connections);
5592
5593
if (items.is_empty()) {
5594
return;
5595
}
5596
5597
_dup_paste_nodes(type, items, node_connections, Vector2(10, 10) * EDSCALE, true);
5598
}
5599
5600
void VisualShaderEditor::_copy_nodes(bool p_cut) {
5601
_clear_copy_buffer();
5602
5603
_dup_copy_nodes(get_current_shader_type(), copy_items_buffer, copy_connections_buffer);
5604
5605
if (p_cut) {
5606
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5607
undo_redo->create_action(TTR("Cut VisualShader Node(s)"));
5608
5609
List<int> ids;
5610
for (const CopyItem &E : copy_items_buffer) {
5611
ids.push_back(E.id);
5612
}
5613
5614
_delete_nodes(get_current_shader_type(), ids);
5615
5616
undo_redo->commit_action();
5617
}
5618
}
5619
5620
void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2 &p_custom_position) {
5621
if (copy_items_buffer.is_empty()) {
5622
return;
5623
}
5624
5625
int type = get_current_shader_type();
5626
5627
float scale = graph->get_zoom();
5628
5629
Vector2 mpos;
5630
if (p_use_custom_position) {
5631
mpos = p_custom_position;
5632
} else {
5633
mpos = graph->get_local_mouse_position();
5634
}
5635
5636
_dup_paste_nodes(type, copy_items_buffer, copy_connections_buffer, graph->get_scroll_offset() / scale + mpos / scale - selection_center, false);
5637
}
5638
5639
void VisualShaderEditor::_type_selected(int p_id) {
5640
int offset = VisualShader::TYPE_VERTEX;
5641
if (mode & MODE_FLAGS_PARTICLES) {
5642
offset = VisualShader::TYPE_START;
5643
if (p_id + offset > VisualShader::TYPE_PROCESS) {
5644
custom_mode_box->set_visible(false);
5645
custom_mode_enabled = false;
5646
} else {
5647
custom_mode_box->set_visible(true);
5648
if (custom_mode_box->is_pressed()) {
5649
custom_mode_enabled = true;
5650
offset += 3;
5651
}
5652
}
5653
} else if (mode & MODE_FLAGS_SKY) {
5654
offset = VisualShader::TYPE_SKY;
5655
} else if (mode & MODE_FLAGS_FOG) {
5656
offset = VisualShader::TYPE_FOG;
5657
}
5658
5659
set_current_shader_type(VisualShader::Type(p_id + offset));
5660
_update_nodes();
5661
_update_graph();
5662
5663
graph->grab_focus();
5664
}
5665
5666
void VisualShaderEditor::_custom_mode_toggled(bool p_enabled) {
5667
if (!(mode & MODE_FLAGS_PARTICLES)) {
5668
return;
5669
}
5670
custom_mode_enabled = p_enabled;
5671
int id = edit_type->get_selected() + 3;
5672
if (p_enabled) {
5673
set_current_shader_type(VisualShader::Type(id + 3));
5674
} else {
5675
set_current_shader_type(VisualShader::Type(id));
5676
}
5677
_update_options_menu();
5678
_update_graph();
5679
}
5680
5681
void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input, const String &p_name) {
5682
String prev_name = p_input->get_input_name();
5683
5684
if (p_name == prev_name) {
5685
return;
5686
}
5687
5688
VisualShaderNode::PortType next_input_type = p_input->get_input_type_by_name(p_name);
5689
VisualShaderNode::PortType prev_input_type = p_input->get_input_type_by_name(prev_name);
5690
5691
bool type_changed = next_input_type != prev_input_type;
5692
5693
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5694
undo_redo_man->create_action(TTR("Visual Shader Input Type Changed"));
5695
5696
undo_redo_man->add_do_method(p_input.ptr(), "set_input_name", p_name);
5697
undo_redo_man->add_undo_method(p_input.ptr(), "set_input_name", prev_name);
5698
5699
if (type_changed) {
5700
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5701
VisualShader::Type type = VisualShader::Type(type_id);
5702
5703
int id = visual_shader->find_node_id(type, p_input);
5704
if (id != VisualShader::NODE_ID_INVALID) {
5705
bool is_expanded = p_input->is_output_port_expandable(0) && p_input->_is_output_port_expanded(0);
5706
5707
int type_size = 0;
5708
if (is_expanded) {
5709
switch (next_input_type) {
5710
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
5711
type_size = 2;
5712
} break;
5713
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
5714
type_size = 3;
5715
} break;
5716
case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
5717
type_size = 4;
5718
} break;
5719
default:
5720
break;
5721
}
5722
}
5723
5724
List<VisualShader::Connection> conns;
5725
visual_shader->get_node_connections(type, &conns);
5726
for (const VisualShader::Connection &E : conns) {
5727
int cn_from_node = E.from_node;
5728
int cn_from_port = E.from_port;
5729
int cn_to_node = E.to_node;
5730
int cn_to_port = E.to_port;
5731
5732
if (cn_from_node == id) {
5733
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));
5734
5735
if (is_incompatible_types || cn_from_port > type_size) {
5736
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5737
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5738
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5739
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, cn_from_node, cn_from_port, cn_to_node, cn_to_port);
5740
}
5741
}
5742
}
5743
5744
undo_redo_man->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
5745
undo_redo_man->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
5746
}
5747
}
5748
}
5749
5750
undo_redo_man->commit_action();
5751
}
5752
5753
void VisualShaderEditor::_parameter_ref_select_item(Ref<VisualShaderNodeParameterRef> p_parameter_ref, const String &p_name) {
5754
String prev_name = p_parameter_ref->get_parameter_name();
5755
5756
if (p_name == prev_name) {
5757
return;
5758
}
5759
5760
bool type_changed = p_parameter_ref->get_parameter_type_by_name(p_name) != p_parameter_ref->get_parameter_type_by_name(prev_name);
5761
5762
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5763
undo_redo_man->create_action(TTR("ParameterRef Name Changed"));
5764
5765
undo_redo_man->add_do_method(p_parameter_ref.ptr(), "set_parameter_name", p_name);
5766
undo_redo_man->add_undo_method(p_parameter_ref.ptr(), "set_parameter_name", prev_name);
5767
5768
// update output port
5769
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5770
VisualShader::Type type = VisualShader::Type(type_id);
5771
int id = visual_shader->find_node_id(type, p_parameter_ref);
5772
if (id != VisualShader::NODE_ID_INVALID) {
5773
if (type_changed) {
5774
List<VisualShader::Connection> conns;
5775
visual_shader->get_node_connections(type, &conns);
5776
for (const VisualShader::Connection &E : conns) {
5777
if (E.from_node == id) {
5778
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))) {
5779
continue;
5780
}
5781
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5782
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5783
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5784
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
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
break;
5791
}
5792
}
5793
5794
undo_redo_man->commit_action();
5795
}
5796
5797
void VisualShaderEditor::_varying_select_item(Ref<VisualShaderNodeVarying> p_varying, const String &p_name) {
5798
String prev_name = p_varying->get_varying_name();
5799
5800
if (p_name == prev_name) {
5801
return;
5802
}
5803
5804
bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
5805
5806
EditorUndoRedoManager *undo_redo_man = EditorUndoRedoManager::get_singleton();
5807
undo_redo_man->create_action(TTR("Varying Name Changed"));
5808
5809
undo_redo_man->add_do_method(p_varying.ptr(), "set_varying_name", p_name);
5810
undo_redo_man->add_undo_method(p_varying.ptr(), "set_varying_name", prev_name);
5811
5812
VisualShader::VaryingType vtype = p_varying->get_varying_type_by_name(p_name);
5813
VisualShader::VaryingType prev_vtype = p_varying->get_varying_type_by_name(prev_name);
5814
5815
bool type_changed = vtype != prev_vtype;
5816
5817
if (type_changed) {
5818
undo_redo_man->add_do_method(p_varying.ptr(), "set_varying_type", vtype);
5819
undo_redo_man->add_undo_method(p_varying.ptr(), "set_varying_type", prev_vtype);
5820
}
5821
5822
// update ports
5823
for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
5824
VisualShader::Type type = VisualShader::Type(type_id);
5825
int id = visual_shader->find_node_id(type, p_varying);
5826
5827
if (id != VisualShader::NODE_ID_INVALID) {
5828
if (type_changed) {
5829
List<VisualShader::Connection> conns;
5830
visual_shader->get_node_connections(type, &conns);
5831
5832
for (const VisualShader::Connection &E : conns) {
5833
if (is_getter) {
5834
if (E.from_node == id) {
5835
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))) {
5836
continue;
5837
}
5838
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5839
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5840
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5841
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5842
}
5843
} else {
5844
if (E.to_node == id) {
5845
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))) {
5846
continue;
5847
}
5848
undo_redo_man->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5849
undo_redo_man->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5850
undo_redo_man->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5851
undo_redo_man->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
5852
}
5853
}
5854
}
5855
}
5856
5857
undo_redo_man->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
5858
undo_redo_man->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
5859
break;
5860
}
5861
}
5862
5863
undo_redo_man->commit_action();
5864
}
5865
5866
void VisualShaderEditor::_float_constant_selected(int p_which) {
5867
ERR_FAIL_INDEX(p_which, MAX_FLOAT_CONST_DEFS);
5868
5869
VisualShader::Type type = get_current_shader_type();
5870
Ref<VisualShaderNodeFloatConstant> node = visual_shader->get_node(type, selected_float_constant);
5871
ERR_FAIL_COND(node.is_null());
5872
5873
if (Math::is_equal_approx(node->get_constant(), float_constant_defs[p_which].value)) {
5874
return; // same
5875
}
5876
5877
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
5878
undo_redo->create_action(vformat(TTR("Set Constant: %s"), float_constant_defs[p_which].name));
5879
undo_redo->add_do_method(node.ptr(), "set_constant", float_constant_defs[p_which].value);
5880
undo_redo->add_undo_method(node.ptr(), "set_constant", node->get_constant());
5881
undo_redo->commit_action();
5882
}
5883
5884
void VisualShaderEditor::_member_filter_changed(const String &p_text) {
5885
_update_options_menu();
5886
}
5887
5888
void VisualShaderEditor::_member_selected() {
5889
TreeItem *item = members->get_selected();
5890
5891
if (item != nullptr && item->has_meta("id")) {
5892
members_dialog->get_ok_button()->set_disabled(false);
5893
highend_label->set_visible(add_options[item->get_meta("id")].highend);
5894
node_desc->set_text(_get_description(item->get_meta("id")));
5895
} else {
5896
highend_label->set_visible(false);
5897
members_dialog->get_ok_button()->set_disabled(true);
5898
node_desc->set_text("");
5899
}
5900
}
5901
5902
void VisualShaderEditor::_member_create() {
5903
TreeItem *item = members->get_selected();
5904
if (item != nullptr && item->has_meta("id")) {
5905
int idx = members->get_selected()->get_meta("id");
5906
if (connection_node_insert_requested) {
5907
from_node = String(clicked_connection->from_node).to_int();
5908
from_slot = clicked_connection->from_port;
5909
to_node = String(clicked_connection->to_node).to_int();
5910
to_slot = clicked_connection->to_port;
5911
5912
connection_node_insert_requested = false;
5913
5914
saved_node_pos_dirty = true;
5915
5916
// Find both graph nodes and get their positions.
5917
GraphNode *from_graph_element = Object::cast_to<GraphNode>(graph->get_node(itos(from_node)));
5918
GraphNode *to_graph_element = Object::cast_to<GraphNode>(graph->get_node(itos(to_node)));
5919
5920
ERR_FAIL_NULL(from_graph_element);
5921
ERR_FAIL_NULL(to_graph_element);
5922
5923
// Since the size of the node to add is not known yet, it's not possible to center it exactly.
5924
float zoom = graph->get_zoom();
5925
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));
5926
}
5927
_add_node(idx, add_options[idx].ops);
5928
members_dialog->hide();
5929
}
5930
}
5931
5932
void VisualShaderEditor::_member_cancel() {
5933
to_node = -1;
5934
to_slot = -1;
5935
from_node = -1;
5936
from_slot = -1;
5937
connection_node_insert_requested = false;
5938
}
5939
5940
void VisualShaderEditor::_update_varying_tree() {
5941
varyings->clear();
5942
TreeItem *root = varyings->create_item();
5943
5944
int count = visual_shader->get_varyings_count();
5945
5946
for (int i = 0; i < count; i++) {
5947
const VisualShader::Varying *varying = visual_shader->get_varying_by_index(i);
5948
5949
if (varying) {
5950
TreeItem *item = varyings->create_item(root);
5951
item->set_text(0, varying->name);
5952
5953
if (i == 0) {
5954
item->select(0);
5955
}
5956
5957
switch (varying->type) {
5958
case VisualShader::VARYING_TYPE_FLOAT:
5959
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)));
5960
break;
5961
case VisualShader::VARYING_TYPE_INT:
5962
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)));
5963
break;
5964
case VisualShader::VARYING_TYPE_UINT:
5965
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)));
5966
break;
5967
case VisualShader::VARYING_TYPE_VECTOR_2D:
5968
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)));
5969
break;
5970
case VisualShader::VARYING_TYPE_VECTOR_3D:
5971
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)));
5972
break;
5973
case VisualShader::VARYING_TYPE_VECTOR_4D:
5974
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)));
5975
break;
5976
case VisualShader::VARYING_TYPE_BOOLEAN:
5977
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)));
5978
break;
5979
case VisualShader::VARYING_TYPE_TRANSFORM:
5980
item->set_icon(0, EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)));
5981
break;
5982
default:
5983
break;
5984
}
5985
}
5986
}
5987
5988
varying_button->get_popup()->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
5989
}
5990
5991
void VisualShaderEditor::_varying_create() {
5992
_add_varying(varying_name->get_text(), (VisualShader::VaryingMode)varying_mode->get_selected(), (VisualShader::VaryingType)varying_type->get_selected());
5993
add_varying_dialog->hide();
5994
}
5995
5996
void VisualShaderEditor::_varying_validate() {
5997
bool has_error = false;
5998
String error;
5999
String varname = varying_name->get_text();
6000
6001
if (!varname.is_valid_ascii_identifier()) {
6002
error += TTR("Invalid name for varying.");
6003
has_error = true;
6004
} else if (visual_shader->has_varying(varname)) {
6005
error += TTR("Varying with that name already exists.");
6006
has_error = true;
6007
}
6008
6009
if (varying_type->get_selected() == 6 && varying_mode->get_selected() == VisualShader::VaryingMode::VARYING_MODE_VERTEX_TO_FRAG_LIGHT) {
6010
if (has_error) {
6011
error += "\n";
6012
}
6013
error += vformat(TTR("Boolean type cannot be used with `%s` varying mode."), "Vertex -> [Fragment, Light]");
6014
has_error = true;
6015
}
6016
6017
if (has_error) {
6018
varying_error_label->show();
6019
varying_error_label->set_text(error);
6020
add_varying_dialog->get_ok_button()->set_disabled(true);
6021
} else {
6022
varying_error_label->hide();
6023
varying_error_label->set_text("");
6024
add_varying_dialog->get_ok_button()->set_disabled(false);
6025
}
6026
add_varying_dialog->reset_size();
6027
}
6028
6029
void VisualShaderEditor::_varying_type_changed(int p_index) {
6030
_varying_validate();
6031
}
6032
6033
void VisualShaderEditor::_varying_mode_changed(int p_index) {
6034
_varying_validate();
6035
}
6036
6037
void VisualShaderEditor::_varying_name_changed(const String &p_name) {
6038
_varying_validate();
6039
}
6040
6041
void VisualShaderEditor::_varying_deleted() {
6042
TreeItem *item = varyings->get_selected();
6043
6044
if (item != nullptr) {
6045
_remove_varying(item->get_text(0));
6046
remove_varying_dialog->hide();
6047
}
6048
}
6049
6050
void VisualShaderEditor::_varying_selected() {
6051
add_varying_dialog->get_ok_button()->set_disabled(false);
6052
}
6053
6054
void VisualShaderEditor::_varying_unselected() {
6055
add_varying_dialog->get_ok_button()->set_disabled(true);
6056
}
6057
6058
void VisualShaderEditor::_tools_menu_option(int p_idx) {
6059
TreeItem *category = members->get_root()->get_first_child();
6060
6061
switch (p_idx) {
6062
case EXPAND_ALL:
6063
6064
while (category) {
6065
category->set_collapsed(false);
6066
TreeItem *sub_category = category->get_first_child();
6067
while (sub_category) {
6068
sub_category->set_collapsed(false);
6069
sub_category = sub_category->get_next();
6070
}
6071
category = category->get_next();
6072
}
6073
6074
break;
6075
6076
case COLLAPSE_ALL:
6077
6078
while (category) {
6079
category->set_collapsed(true);
6080
TreeItem *sub_category = category->get_first_child();
6081
while (sub_category) {
6082
sub_category->set_collapsed(true);
6083
sub_category = sub_category->get_next();
6084
}
6085
category = category->get_next();
6086
}
6087
6088
break;
6089
default:
6090
break;
6091
}
6092
}
6093
6094
void VisualShaderEditor::_node_menu_id_pressed(int p_idx) {
6095
switch (p_idx) {
6096
case NodeMenuOptions::ADD:
6097
_show_members_dialog(true);
6098
break;
6099
case NodeMenuOptions::CUT:
6100
_copy_nodes(true);
6101
break;
6102
case NodeMenuOptions::COPY:
6103
_copy_nodes(false);
6104
break;
6105
case NodeMenuOptions::PASTE:
6106
_paste_nodes(true, menu_point);
6107
break;
6108
case NodeMenuOptions::DELETE_:
6109
_delete_nodes_request(TypedArray<StringName>());
6110
break;
6111
case NodeMenuOptions::DUPLICATE:
6112
_duplicate_nodes();
6113
break;
6114
case NodeMenuOptions::CLEAR_COPY_BUFFER:
6115
_clear_copy_buffer();
6116
break;
6117
case NodeMenuOptions::CONVERT_CONSTANTS_TO_PARAMETERS:
6118
_convert_constants_to_parameters(false);
6119
break;
6120
case NodeMenuOptions::CONVERT_PARAMETERS_TO_CONSTANTS:
6121
_convert_constants_to_parameters(true);
6122
break;
6123
case NodeMenuOptions::UNLINK_FROM_PARENT_FRAME:
6124
_detach_nodes_from_frame_request();
6125
break;
6126
case NodeMenuOptions::SET_FRAME_TITLE:
6127
_frame_title_popup_show(get_screen_position() + get_local_mouse_position(), selected_frame);
6128
break;
6129
case NodeMenuOptions::ENABLE_FRAME_COLOR:
6130
_frame_color_enabled_changed(selected_frame);
6131
break;
6132
case NodeMenuOptions::SET_FRAME_COLOR:
6133
_frame_color_popup_show(get_screen_position() + get_local_mouse_position(), selected_frame);
6134
break;
6135
case NodeMenuOptions::ENABLE_FRAME_AUTOSHRINK:
6136
_frame_autoshrink_enabled_changed(selected_frame);
6137
break;
6138
default:
6139
break;
6140
}
6141
}
6142
6143
void VisualShaderEditor::_connection_menu_id_pressed(int p_idx) {
6144
switch (p_idx) {
6145
case ConnectionMenuOptions::DISCONNECT: {
6146
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
6147
undo_redo->create_action(TTR("Disconnect"));
6148
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);
6149
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);
6150
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);
6151
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);
6152
undo_redo->commit_action();
6153
} break;
6154
case ConnectionMenuOptions::INSERT_NEW_NODE: {
6155
VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX;
6156
VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX;
6157
Ref<VisualShaderNode> node1 = visual_shader->get_node(get_current_shader_type(), String(clicked_connection->from_node).to_int());
6158
if (node1.is_valid()) {
6159
output_port_type = node1->get_output_port_type(from_slot);
6160
}
6161
Ref<VisualShaderNode> node2 = visual_shader->get_node(get_current_shader_type(), String(clicked_connection->to_node).to_int());
6162
if (node2.is_valid()) {
6163
input_port_type = node2->get_input_port_type(to_slot);
6164
}
6165
6166
connection_node_insert_requested = true;
6167
_show_members_dialog(true, input_port_type, output_port_type);
6168
} break;
6169
case ConnectionMenuOptions::INSERT_NEW_REROUTE: {
6170
from_node = String(clicked_connection->from_node).to_int();
6171
from_slot = clicked_connection->from_port;
6172
to_node = String(clicked_connection->to_node).to_int();
6173
to_slot = clicked_connection->to_port;
6174
6175
// Manual offset to place the port exactly at the mouse position.
6176
saved_node_pos -= Vector2(11 * EDSCALE * graph->get_zoom(), 50 * EDSCALE * graph->get_zoom());
6177
6178
// Find reroute addoptions.
6179
int idx = -1;
6180
for (int i = 0; i < add_options.size(); i++) {
6181
if (add_options[i].name == "Reroute") {
6182
idx = i;
6183
break;
6184
}
6185
}
6186
_add_node(idx, add_options[idx].ops);
6187
} break;
6188
default:
6189
break;
6190
}
6191
}
6192
6193
Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
6194
if (p_point == Vector2(Math::INF, Math::INF)) {
6195
return Variant();
6196
}
6197
6198
if (p_from == members) {
6199
TreeItem *it = members->get_item_at_position(p_point);
6200
if (!it) {
6201
return Variant();
6202
}
6203
if (!it->has_meta("id")) {
6204
return Variant();
6205
}
6206
6207
int id = it->get_meta("id");
6208
AddOption op = add_options[id];
6209
6210
Dictionary d;
6211
d["id"] = id;
6212
6213
Label *label = memnew(Label);
6214
label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6215
label->set_text(it->get_text(0));
6216
label->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
6217
set_drag_preview(label);
6218
return d;
6219
}
6220
return Variant();
6221
}
6222
6223
bool VisualShaderEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
6224
if (p_point == Vector2(Math::INF, Math::INF)) {
6225
return false;
6226
}
6227
6228
if (p_from == graph) {
6229
Dictionary d = p_data;
6230
6231
if (d.has("id")) {
6232
return true;
6233
}
6234
if (d.has("files")) {
6235
return true;
6236
}
6237
}
6238
6239
return false;
6240
}
6241
6242
void VisualShaderEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
6243
if (p_point == Vector2(Math::INF, Math::INF)) {
6244
return;
6245
}
6246
6247
if (p_from == graph) {
6248
Dictionary d = p_data;
6249
6250
if (d.has("id")) {
6251
int idx = d["id"];
6252
saved_node_pos = p_point;
6253
saved_node_pos_dirty = true;
6254
_add_node(idx, add_options[idx].ops);
6255
} else if (d.has("files")) {
6256
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
6257
undo_redo->create_action(TTR("Add Node(s) to Visual Shader"));
6258
6259
if (d["files"].get_type() == Variant::PACKED_STRING_ARRAY) {
6260
PackedStringArray arr = d["files"];
6261
for (int i = 0; i < arr.size(); i++) {
6262
String type = ResourceLoader::get_resource_type(arr[i]);
6263
if (type == "GDScript") {
6264
Ref<Script> scr = ResourceLoader::load(arr[i]);
6265
if (scr->get_instance_base_type() == "VisualShaderNodeCustom") {
6266
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6267
saved_node_pos_dirty = true;
6268
6269
int idx = -1;
6270
6271
for (int j = custom_node_option_idx; j < add_options.size(); j++) {
6272
if (add_options[j].script.is_valid()) {
6273
if (add_options[j].script->get_path() == arr[i]) {
6274
idx = j;
6275
break;
6276
}
6277
}
6278
}
6279
if (idx != -1) {
6280
_add_node(idx, {}, arr[i], i);
6281
}
6282
}
6283
} else if (type == "CurveTexture") {
6284
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6285
saved_node_pos_dirty = true;
6286
_add_node(curve_node_option_idx, {}, arr[i], i);
6287
} else if (type == "CurveXYZTexture") {
6288
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6289
saved_node_pos_dirty = true;
6290
_add_node(curve_xyz_node_option_idx, {}, arr[i], i);
6291
} else if (ClassDB::get_parent_class(type) == "Texture2D") {
6292
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6293
saved_node_pos_dirty = true;
6294
_add_node(texture2d_node_option_idx, {}, arr[i], i);
6295
} else if (type == "Texture2DArray") {
6296
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6297
saved_node_pos_dirty = true;
6298
_add_node(texture2d_array_node_option_idx, {}, arr[i], i);
6299
} else if (ClassDB::get_parent_class(type) == "Texture3D") {
6300
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6301
saved_node_pos_dirty = true;
6302
_add_node(texture3d_node_option_idx, {}, arr[i], i);
6303
} else if (type == "Cubemap") {
6304
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6305
saved_node_pos_dirty = true;
6306
_add_node(cubemap_node_option_idx, {}, arr[i], i);
6307
} else if (type == "Mesh" && visual_shader->get_mode() == Shader::MODE_PARTICLES &&
6308
(get_current_shader_type() == VisualShader::TYPE_START || get_current_shader_type() == VisualShader::TYPE_START_CUSTOM)) {
6309
saved_node_pos = p_point + Vector2(0, i * 250 * EDSCALE);
6310
saved_node_pos_dirty = true;
6311
_add_node(mesh_emitter_option_idx, {}, arr[i], i);
6312
}
6313
}
6314
}
6315
undo_redo->commit_action();
6316
}
6317
}
6318
}
6319
6320
void VisualShaderEditor::_show_preview_text() {
6321
code_preview_showed = !code_preview_showed;
6322
if (code_preview_showed) {
6323
if (code_preview_first) {
6324
code_preview_window->set_size(Size2(400 * EDSCALE, 600 * EDSCALE));
6325
code_preview_window->popup_centered();
6326
code_preview_first = false;
6327
} else {
6328
code_preview_window->popup();
6329
}
6330
6331
if (pending_update_preview) {
6332
_update_preview();
6333
pending_update_preview = false;
6334
}
6335
} else {
6336
code_preview_window->hide();
6337
}
6338
}
6339
6340
void VisualShaderEditor::_preview_close_requested() {
6341
code_preview_showed = false;
6342
code_preview_button->set_pressed(false);
6343
}
6344
6345
static ShaderLanguage::DataType _visual_shader_editor_get_global_shader_uniform_type(const StringName &p_variable) {
6346
RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_variable);
6347
return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
6348
}
6349
6350
void VisualShaderEditor::_update_preview() {
6351
if (!code_preview_showed) {
6352
pending_update_preview = true;
6353
return;
6354
}
6355
6356
String code = visual_shader->get_code();
6357
6358
preview_text->set_text(code);
6359
6360
ShaderLanguage::ShaderCompileInfo info;
6361
info.functions = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode()));
6362
info.render_modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
6363
info.stencil_modes = ShaderTypes::get_singleton()->get_stencil_modes(RenderingServer::ShaderMode(visual_shader->get_mode()));
6364
info.shader_types = ShaderTypes::get_singleton()->get_types();
6365
info.global_shader_uniform_type_func = _visual_shader_editor_get_global_shader_uniform_type;
6366
6367
for (int i = 0; i < preview_text->get_line_count(); i++) {
6368
preview_text->set_line_background_color(i, Color(0, 0, 0, 0));
6369
}
6370
6371
String preprocessed_code;
6372
{
6373
String path = visual_shader->get_path();
6374
String error_pp;
6375
List<ShaderPreprocessor::FilePosition> err_positions;
6376
ShaderPreprocessor preprocessor;
6377
Error err = preprocessor.preprocess(code, path, preprocessed_code, &error_pp, &err_positions);
6378
if (err != OK) {
6379
ERR_FAIL_COND(err_positions.is_empty());
6380
6381
String file = err_positions.front()->get().file;
6382
int err_line = err_positions.front()->get().line;
6383
Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
6384
preview_text->set_line_background_color(err_line - 1, error_line_color);
6385
error_panel->show();
6386
6387
error_label->set_text("error(" + file + ":" + itos(err_line) + "): " + error_pp);
6388
shader_error = true;
6389
return;
6390
}
6391
}
6392
6393
ShaderLanguage sl;
6394
Error err = sl.compile(preprocessed_code, info);
6395
if (err != OK) {
6396
int err_line;
6397
String err_text;
6398
Vector<ShaderLanguage::FilePosition> include_positions = sl.get_include_positions();
6399
if (include_positions.size() > 1) {
6400
// Error is in an include.
6401
err_line = include_positions[0].line;
6402
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();
6403
} else {
6404
err_line = sl.get_error_line();
6405
err_text = "error(" + itos(err_line) + "): " + sl.get_error_text();
6406
}
6407
6408
Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color");
6409
preview_text->set_line_background_color(err_line - 1, error_line_color);
6410
error_panel->show();
6411
6412
error_label->set_text(err_text);
6413
shader_error = true;
6414
} else {
6415
error_panel->hide();
6416
shader_error = false;
6417
}
6418
}
6419
6420
void VisualShaderEditor::_update_next_previews(int p_node_id) {
6421
VisualShader::Type type = get_current_shader_type();
6422
6423
LocalVector<int> nodes;
6424
_get_next_nodes_recursively(type, p_node_id, nodes);
6425
6426
for (int node_id : nodes) {
6427
if (graph_plugin->is_preview_visible(node_id)) {
6428
graph_plugin->update_node_deferred(type, node_id);
6429
}
6430
}
6431
}
6432
6433
void VisualShaderEditor::_get_next_nodes_recursively(VisualShader::Type p_type, int p_node_id, LocalVector<int> &r_nodes) const {
6434
const LocalVector<int> &next_connections = visual_shader->get_next_connected_nodes(p_type, p_node_id);
6435
6436
for (int node_id : next_connections) {
6437
r_nodes.push_back(node_id);
6438
_get_next_nodes_recursively(p_type, node_id, r_nodes);
6439
}
6440
}
6441
6442
void VisualShaderEditor::_visibility_changed() {
6443
if (!is_visible()) {
6444
if (code_preview_window->is_visible()) {
6445
code_preview_button->set_pressed(false);
6446
code_preview_window->hide();
6447
code_preview_showed = false;
6448
}
6449
}
6450
}
6451
6452
void VisualShaderEditor::_show_shader_preview() {
6453
shader_preview_showed = !shader_preview_showed;
6454
if (shader_preview_showed) {
6455
shader_preview_vbox->show();
6456
} else {
6457
shader_preview_vbox->hide();
6458
6459
_param_unselected();
6460
}
6461
}
6462
6463
void VisualShaderEditor::set_toggle_list_control(Control *p_control) {
6464
toggle_files_list = p_control;
6465
}
6466
6467
void VisualShaderEditor::_toggle_files_pressed() {
6468
ERR_FAIL_NULL(toggle_files_list);
6469
toggle_files_list->set_visible(!toggle_files_list->is_visible());
6470
update_toggle_files_button();
6471
}
6472
6473
void VisualShaderEditor::_bind_methods() {
6474
ClassDB::bind_method("_update_nodes", &VisualShaderEditor::_update_nodes);
6475
ClassDB::bind_method("_update_graph", &VisualShaderEditor::_update_graph);
6476
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
6477
ClassDB::bind_method("_parameter_ref_select_item", &VisualShaderEditor::_parameter_ref_select_item);
6478
ClassDB::bind_method("_varying_select_item", &VisualShaderEditor::_varying_select_item);
6479
ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size);
6480
ClassDB::bind_method("_update_parameters", &VisualShaderEditor::_update_parameters);
6481
ClassDB::bind_method("_update_varyings", &VisualShaderEditor::_update_varyings);
6482
ClassDB::bind_method("_update_varying_tree", &VisualShaderEditor::_update_varying_tree);
6483
ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode);
6484
ClassDB::bind_method("_update_constant", &VisualShaderEditor::_update_constant);
6485
ClassDB::bind_method("_update_parameter", &VisualShaderEditor::_update_parameter);
6486
ClassDB::bind_method("_update_next_previews", &VisualShaderEditor::_update_next_previews);
6487
ClassDB::bind_method("_update_current_param", &VisualShaderEditor::_update_current_param);
6488
}
6489
6490
VisualShaderEditor::VisualShaderEditor() {
6491
vs_editor_cache.instantiate();
6492
vs_editor_cache->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("vs_editor_cache.cfg"));
6493
6494
ShaderLanguage::get_keyword_list(&keyword_list);
6495
EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &VisualShaderEditor::_resource_saved));
6496
FileSystemDock::get_singleton()->get_script_create_dialog()->connect("script_created", callable_mp(this, &VisualShaderEditor::_script_created));
6497
FileSystemDock::get_singleton()->connect("resource_removed", callable_mp(this, &VisualShaderEditor::_resource_removed));
6498
6499
HSplitContainer *main_box = memnew(HSplitContainer);
6500
main_box->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
6501
add_child(main_box);
6502
6503
graph = memnew(GraphEdit);
6504
graph->set_v_size_flags(SIZE_EXPAND_FILL);
6505
graph->set_h_size_flags(SIZE_EXPAND_FILL);
6506
graph->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
6507
graph->set_grid_pattern(GraphEdit::GridPattern::GRID_PATTERN_DOTS);
6508
int grid_pattern = EDITOR_GET("editors/visual_editors/grid_pattern");
6509
graph->set_grid_pattern((GraphEdit::GridPattern)grid_pattern);
6510
graph->set_show_zoom_label(true);
6511
main_box->add_child(graph);
6512
SET_DRAG_FORWARDING_GCD(graph, VisualShaderEditor);
6513
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
6514
graph->set_minimap_opacity(graph_minimap_opacity);
6515
float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature");
6516
graph->set_connection_lines_curvature(graph_lines_curvature);
6517
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR);
6518
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR_INT);
6519
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6520
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN);
6521
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_2D);
6522
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_3D);
6523
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_4D);
6524
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM);
6525
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
6526
//graph->add_valid_left_disconnect_type(0);
6527
graph->set_v_size_flags(SIZE_EXPAND_FILL);
6528
graph->connect("connection_request", callable_mp(this, &VisualShaderEditor::_connection_request), CONNECT_DEFERRED);
6529
graph->connect("disconnection_request", callable_mp(this, &VisualShaderEditor::_disconnection_request), CONNECT_DEFERRED);
6530
graph->connect("node_selected", callable_mp(this, &VisualShaderEditor::_node_selected));
6531
graph->connect("scroll_offset_changed", callable_mp(this, &VisualShaderEditor::_scroll_offset_changed));
6532
graph->connect("duplicate_nodes_request", callable_mp(this, &VisualShaderEditor::_duplicate_nodes));
6533
graph->connect("copy_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(false));
6534
graph->connect("cut_nodes_request", callable_mp(this, &VisualShaderEditor::_copy_nodes).bind(true));
6535
graph->connect("paste_nodes_request", callable_mp(this, &VisualShaderEditor::_paste_nodes).bind(false, Point2()));
6536
graph->connect("delete_nodes_request", callable_mp(this, &VisualShaderEditor::_delete_nodes_request));
6537
graph->connect(SceneStringName(gui_input), callable_mp(this, &VisualShaderEditor::_graph_gui_input));
6538
graph->connect("connection_to_empty", callable_mp(this, &VisualShaderEditor::_connection_to_empty));
6539
graph->connect("connection_from_empty", callable_mp(this, &VisualShaderEditor::_connection_from_empty));
6540
graph->connect("connection_drag_ended", callable_mp(this, &VisualShaderEditor::_connection_drag_ended));
6541
graph->connect(SceneStringName(visibility_changed), callable_mp(this, &VisualShaderEditor::_visibility_changed));
6542
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
6543
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6544
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6545
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6546
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6547
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6548
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
6549
6550
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR);
6551
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6552
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6553
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6554
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6555
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6556
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_BOOLEAN);
6557
6558
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR);
6559
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6560
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6561
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6562
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6563
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6564
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_UINT, VisualShaderNode::PORT_TYPE_BOOLEAN);
6565
6566
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR);
6567
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6568
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6569
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6570
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6571
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6572
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6573
6574
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR);
6575
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6576
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6577
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6578
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6579
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6580
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6581
6582
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR);
6583
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6584
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6585
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6586
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6587
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6588
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_BOOLEAN);
6589
6590
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR);
6591
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_INT);
6592
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_UINT);
6593
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_2D);
6594
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_3D);
6595
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_4D);
6596
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN);
6597
6598
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
6599
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
6600
6601
info_label = memnew(Label);
6602
info_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6603
info_label->set_text(vformat(TTR("Hold %s Key To Swap Connections"), keycode_get_string((Key)KeyModifierMask::CMD_OR_CTRL)));
6604
info_label->set_anchors_and_offsets_preset(Control::PRESET_BOTTOM_WIDE, PRESET_MODE_MINSIZE, 20);
6605
info_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
6606
info_label->hide();
6607
graph->get_top_layer()->add_child(info_label);
6608
6609
PanelContainer *toolbar_panel = static_cast<PanelContainer *>(graph->get_menu_hbox()->get_parent());
6610
toolbar_panel->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE, PRESET_MODE_MINSIZE, 10);
6611
toolbar_panel->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
6612
6613
toolbar_hflow = memnew(HFlowContainer);
6614
{
6615
LocalVector<Node *> nodes;
6616
for (int i = 0; i < graph->get_menu_hbox()->get_child_count(); i++) {
6617
Node *child = graph->get_menu_hbox()->get_child(i);
6618
nodes.push_back(child);
6619
}
6620
6621
for (Node *node : nodes) {
6622
graph->get_menu_hbox()->remove_child(node);
6623
toolbar_hflow->add_child(node);
6624
}
6625
6626
graph->get_menu_hbox()->hide();
6627
toolbar_panel->add_child(toolbar_hflow);
6628
}
6629
6630
VSeparator *vs = memnew(VSeparator);
6631
toolbar_hflow->add_child(vs);
6632
toolbar_hflow->move_child(vs, 0);
6633
6634
custom_mode_box = memnew(CheckBox);
6635
custom_mode_box->set_text(TTR("Custom"));
6636
custom_mode_box->set_pressed(false);
6637
custom_mode_box->set_visible(false);
6638
custom_mode_box->connect(SceneStringName(toggled), callable_mp(this, &VisualShaderEditor::_custom_mode_toggled));
6639
6640
edit_type_standard = memnew(OptionButton);
6641
edit_type_standard->add_item(TTR("Vertex"));
6642
edit_type_standard->add_item(TTR("Fragment"));
6643
edit_type_standard->add_item(TTR("Light"));
6644
edit_type_standard->select(1);
6645
edit_type_standard->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6646
6647
edit_type_particles = memnew(OptionButton);
6648
edit_type_particles->add_item(TTR("Start"));
6649
edit_type_particles->add_item(TTR("Process"));
6650
edit_type_particles->add_item(TTR("Collide"));
6651
edit_type_particles->select(0);
6652
edit_type_particles->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6653
6654
edit_type_sky = memnew(OptionButton);
6655
edit_type_sky->add_item(TTR("Sky"));
6656
edit_type_sky->select(0);
6657
edit_type_sky->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6658
6659
edit_type_fog = memnew(OptionButton);
6660
edit_type_fog->add_item(TTR("Fog"));
6661
edit_type_fog->select(0);
6662
edit_type_fog->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
6663
6664
edit_type = edit_type_standard;
6665
6666
toolbar_hflow->add_child(custom_mode_box);
6667
toolbar_hflow->move_child(custom_mode_box, 0);
6668
toolbar_hflow->add_child(edit_type_standard);
6669
toolbar_hflow->move_child(edit_type_standard, 0);
6670
toolbar_hflow->add_child(edit_type_particles);
6671
toolbar_hflow->move_child(edit_type_particles, 0);
6672
toolbar_hflow->add_child(edit_type_sky);
6673
toolbar_hflow->move_child(edit_type_sky, 0);
6674
toolbar_hflow->add_child(edit_type_fog);
6675
toolbar_hflow->move_child(edit_type_fog, 0);
6676
6677
add_node = memnew(Button);
6678
add_node->set_theme_type_variation(SceneStringName(FlatButton));
6679
add_node->set_text(TTR("Add Node..."));
6680
toolbar_hflow->add_child(add_node);
6681
toolbar_hflow->move_child(add_node, 0);
6682
add_node->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_members_dialog).bind(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
6683
6684
graph->connect("graph_elements_linked_to_frame_request", callable_mp(this, &VisualShaderEditor::_nodes_linked_to_frame_request));
6685
graph->connect("frame_rect_changed", callable_mp(this, &VisualShaderEditor::_frame_rect_changed));
6686
6687
varying_button = memnew(MenuButton);
6688
varying_button->set_flat(false);
6689
varying_button->set_theme_type_variation("FlatMenuButton");
6690
varying_button->set_text(TTR("Manage Varyings"));
6691
varying_button->set_switch_on_hover(true);
6692
toolbar_hflow->add_child(varying_button);
6693
6694
PopupMenu *varying_menu = varying_button->get_popup();
6695
varying_menu->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
6696
varying_menu->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
6697
varying_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
6698
6699
code_preview_button = memnew(Button);
6700
code_preview_button->set_theme_type_variation(SceneStringName(FlatButton));
6701
code_preview_button->set_toggle_mode(true);
6702
code_preview_button->set_tooltip_text(TTR("Show generated shader code."));
6703
toolbar_hflow->add_child(code_preview_button);
6704
code_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_preview_text));
6705
6706
shader_preview_button = memnew(Button);
6707
shader_preview_button->set_theme_type_variation(SceneStringName(FlatButton));
6708
shader_preview_button->set_toggle_mode(true);
6709
shader_preview_button->set_tooltip_text(TTR("Toggle shader preview."));
6710
shader_preview_button->set_pressed(true);
6711
toolbar_hflow->add_child(shader_preview_button);
6712
shader_preview_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_show_shader_preview));
6713
6714
Control *spacer = memnew(Control);
6715
spacer->set_h_size_flags(Control::SIZE_EXPAND);
6716
toolbar_hflow->add_child(spacer);
6717
6718
site_search = memnew(Button);
6719
site_search->set_theme_type_variation(SceneStringName(FlatButton));
6720
site_search->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_help_open));
6721
site_search->set_text(TTR("Online Docs"));
6722
site_search->set_tooltip_text(TTR("Open Godot online documentation."));
6723
toolbar_hflow->add_child(site_search);
6724
toolbar_hflow->add_child(memnew(VSeparator));
6725
6726
VSeparator *separator = memnew(VSeparator);
6727
toolbar_hflow->add_child(separator);
6728
toolbar_hflow->move_child(separator, 0);
6729
6730
separator = memnew(VSeparator);
6731
toolbar_hflow->add_child(separator);
6732
toolbar_hflow->move_child(separator, 0);
6733
6734
toggle_files_button = memnew(Button);
6735
toggle_files_button->set_theme_type_variation(SceneStringName(FlatButton));
6736
toggle_files_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_toggle_files_pressed));
6737
toolbar_hflow->add_child(toggle_files_button);
6738
toolbar_hflow->move_child(toggle_files_button, 0);
6739
6740
///////////////////////////////////////
6741
// CODE PREVIEW
6742
///////////////////////////////////////
6743
6744
code_preview_window = memnew(AcceptDialog);
6745
code_preview_window->set_title(TTR("Generated Shader Code"));
6746
code_preview_window->set_visible(code_preview_showed);
6747
code_preview_window->set_ok_button_text(TTR("Close"));
6748
code_preview_window->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_preview_close_requested));
6749
code_preview_window->connect("canceled", callable_mp(this, &VisualShaderEditor::_preview_close_requested));
6750
add_child(code_preview_window);
6751
6752
code_preview_vbox = memnew(VBoxContainer);
6753
code_preview_window->add_child(code_preview_vbox);
6754
code_preview_vbox->add_theme_constant_override("separation", 0);
6755
6756
preview_text = memnew(CodeEdit);
6757
syntax_highlighter.instantiate();
6758
code_preview_vbox->add_child(preview_text);
6759
preview_text->set_v_size_flags(Control::SIZE_EXPAND_FILL);
6760
preview_text->set_syntax_highlighter(syntax_highlighter);
6761
preview_text->set_draw_line_numbers(true);
6762
preview_text->set_editable(false);
6763
6764
error_panel = memnew(PanelContainer);
6765
code_preview_vbox->add_child(error_panel);
6766
error_panel->set_visible(false);
6767
6768
error_label = memnew(Label);
6769
error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6770
error_panel->add_child(error_label);
6771
error_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
6772
6773
///////////////////////////////////////
6774
// POPUP MENU
6775
///////////////////////////////////////
6776
6777
popup_menu = memnew(PopupMenu);
6778
add_child(popup_menu);
6779
popup_menu->set_hide_on_checkable_item_selection(false);
6780
popup_menu->add_item(TTR("Add Node"), NodeMenuOptions::ADD);
6781
popup_menu->add_separator();
6782
popup_menu->add_item(TTR("Cut"), NodeMenuOptions::CUT);
6783
popup_menu->add_item(TTR("Copy"), NodeMenuOptions::COPY);
6784
popup_menu->add_item(TTR("Paste"), NodeMenuOptions::PASTE);
6785
popup_menu->add_item(TTR("Delete"), NodeMenuOptions::DELETE_);
6786
popup_menu->add_item(TTR("Duplicate"), NodeMenuOptions::DUPLICATE);
6787
popup_menu->add_item(TTR("Clear Copy Buffer"), NodeMenuOptions::CLEAR_COPY_BUFFER);
6788
popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_node_menu_id_pressed));
6789
6790
connection_popup_menu = memnew(PopupMenu);
6791
add_child(connection_popup_menu);
6792
connection_popup_menu->add_item(TTR("Disconnect"), ConnectionMenuOptions::DISCONNECT);
6793
connection_popup_menu->add_item(TTR("Insert New Node"), ConnectionMenuOptions::INSERT_NEW_NODE);
6794
connection_popup_menu->add_item(TTR("Insert New Reroute"), ConnectionMenuOptions::INSERT_NEW_REROUTE);
6795
connection_popup_menu->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_connection_menu_id_pressed));
6796
6797
///////////////////////////////////////
6798
// SHADER PREVIEW
6799
///////////////////////////////////////
6800
6801
shader_preview_vbox = memnew(VBoxContainer);
6802
shader_preview_vbox->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
6803
main_box->add_child(shader_preview_vbox);
6804
6805
VSplitContainer *preview_split = memnew(VSplitContainer);
6806
preview_split->set_v_size_flags(SIZE_EXPAND_FILL);
6807
shader_preview_vbox->add_child(preview_split);
6808
6809
// Initialize material editor.
6810
{
6811
env.instantiate();
6812
Ref<Sky> sky = memnew(Sky());
6813
env->set_sky(sky);
6814
env->set_background(Environment::BG_COLOR);
6815
env->set_ambient_source(Environment::AMBIENT_SOURCE_SKY);
6816
env->set_reflection_source(Environment::REFLECTION_SOURCE_SKY);
6817
6818
preview_material.instantiate();
6819
preview_material->connect(CoreStringName(property_list_changed), callable_mp(this, &VisualShaderEditor::_update_preview_parameter_list));
6820
6821
material_editor = memnew(MaterialEditor);
6822
preview_split->add_child(material_editor);
6823
}
6824
6825
VBoxContainer *params_vbox = memnew(VBoxContainer);
6826
preview_split->add_child(params_vbox);
6827
6828
HBoxContainer *filter_hbox = memnew(HBoxContainer);
6829
params_vbox->add_child(filter_hbox);
6830
6831
param_filter = memnew(LineEdit);
6832
filter_hbox->add_child(param_filter);
6833
param_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_param_filter_changed));
6834
param_filter->set_h_size_flags(SIZE_EXPAND_FILL);
6835
param_filter->set_placeholder(TTR("Filter Parameters"));
6836
6837
preview_tools = memnew(MenuButton);
6838
filter_hbox->add_child(preview_tools);
6839
preview_tools->set_tooltip_text(TTR("Options"));
6840
preview_tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_preview_tools_menu_option));
6841
preview_tools->get_popup()->add_item(TTR("Copy Parameters From Material"), COPY_PARAMS_FROM_MATERIAL);
6842
preview_tools->get_popup()->add_item(TTR("Paste Parameters To Material"), PASTE_PARAMS_TO_MATERIAL);
6843
6844
ScrollContainer *sc = memnew(ScrollContainer);
6845
sc->set_v_size_flags(SIZE_EXPAND_FILL);
6846
params_vbox->add_child(sc);
6847
6848
parameters = memnew(Tree);
6849
parameters->set_hide_root(true);
6850
parameters->set_allow_reselect(true);
6851
parameters->set_hide_folding(false);
6852
parameters->set_h_size_flags(SIZE_EXPAND_FILL);
6853
parameters->set_v_size_flags(SIZE_EXPAND_FILL);
6854
parameters->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
6855
parameters->set_theme_type_variation("TreeSecondary");
6856
parameters->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_param_selected));
6857
parameters->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_param_unselected));
6858
sc->add_child(parameters);
6859
6860
param_vbox = memnew(VBoxContainer);
6861
param_vbox->set_v_size_flags(SIZE_EXPAND_FILL);
6862
param_vbox->hide();
6863
params_vbox->add_child(param_vbox);
6864
6865
ScrollContainer *sc2 = memnew(ScrollContainer);
6866
sc2->set_v_size_flags(SIZE_EXPAND_FILL);
6867
param_vbox->add_child(sc2);
6868
6869
param_vbox2 = memnew(VBoxContainer);
6870
param_vbox2->set_h_size_flags(SIZE_EXPAND_FILL);
6871
sc2->add_child(param_vbox2);
6872
6873
///////////////////////////////////////
6874
// SHADER NODES TREE
6875
///////////////////////////////////////
6876
6877
VBoxContainer *members_vb = memnew(VBoxContainer);
6878
members_vb->set_v_size_flags(SIZE_EXPAND_FILL);
6879
6880
HBoxContainer *filter_hb = memnew(HBoxContainer);
6881
members_vb->add_child(filter_hb);
6882
6883
node_filter = memnew(LineEdit);
6884
filter_hb->add_child(node_filter);
6885
node_filter->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_member_filter_changed));
6886
node_filter->connect(SceneStringName(gui_input), callable_mp(this, &VisualShaderEditor::_sbox_input));
6887
node_filter->set_h_size_flags(SIZE_EXPAND_FILL);
6888
node_filter->set_placeholder(TTR("Search"));
6889
6890
tools = memnew(MenuButton);
6891
filter_hb->add_child(tools);
6892
tools->set_tooltip_text(TTR("Options"));
6893
tools->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &VisualShaderEditor::_tools_menu_option));
6894
tools->get_popup()->add_item(TTR("Expand All"), EXPAND_ALL);
6895
tools->get_popup()->add_item(TTR("Collapse All"), COLLAPSE_ALL);
6896
6897
members = memnew(Tree);
6898
members_vb->add_child(members);
6899
SET_DRAG_FORWARDING_GCD(members, VisualShaderEditor);
6900
members->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
6901
members->set_h_size_flags(SIZE_EXPAND_FILL);
6902
members->set_v_size_flags(SIZE_EXPAND_FILL);
6903
members->set_hide_root(true);
6904
members->set_allow_reselect(true);
6905
members->set_hide_folding(false);
6906
members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
6907
members->connect("item_activated", callable_mp(this, &VisualShaderEditor::_member_create));
6908
members->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_member_selected));
6909
6910
HBoxContainer *desc_hbox = memnew(HBoxContainer);
6911
members_vb->add_child(desc_hbox);
6912
6913
Label *desc_label = memnew(Label);
6914
desc_hbox->add_child(desc_label);
6915
desc_label->set_text(TTR("Description:"));
6916
6917
desc_hbox->add_spacer();
6918
6919
highend_label = memnew(Label);
6920
highend_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6921
desc_hbox->add_child(highend_label);
6922
highend_label->set_visible(false);
6923
highend_label->set_text("Vulkan");
6924
highend_label->set_mouse_filter(Control::MOUSE_FILTER_STOP);
6925
highend_label->set_tooltip_text(TTR("High-end node"));
6926
6927
node_desc = memnew(RichTextLabel);
6928
members_vb->add_child(node_desc);
6929
node_desc->set_h_size_flags(SIZE_EXPAND_FILL);
6930
node_desc->set_v_size_flags(SIZE_FILL);
6931
node_desc->set_custom_minimum_size(Size2(0, 70 * EDSCALE));
6932
6933
members_dialog = memnew(ConfirmationDialog);
6934
members_dialog->set_title(TTR("Create Shader Node"));
6935
members_dialog->add_child(members_vb);
6936
members_dialog->set_ok_button_text(TTR("Create"));
6937
members_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_member_create));
6938
members_dialog->get_ok_button()->set_disabled(true);
6939
members_dialog->connect("canceled", callable_mp(this, &VisualShaderEditor::_member_cancel));
6940
members_dialog->register_text_enter(node_filter);
6941
add_child(members_dialog);
6942
6943
// add varyings dialog
6944
{
6945
add_varying_dialog = memnew(ConfirmationDialog);
6946
add_varying_dialog->set_title(TTR("Create Shader Varying"));
6947
add_varying_dialog->set_ok_button_text(TTR("Create"));
6948
add_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_create));
6949
add_varying_dialog->get_ok_button()->set_disabled(true);
6950
add_child(add_varying_dialog);
6951
6952
VBoxContainer *vb = memnew(VBoxContainer);
6953
add_varying_dialog->add_child(vb);
6954
6955
HBoxContainer *hb = memnew(HBoxContainer);
6956
vb->add_child(hb);
6957
hb->set_h_size_flags(SIZE_EXPAND_FILL);
6958
6959
varying_type = memnew(OptionButton);
6960
hb->add_child(varying_type);
6961
varying_type->add_item("Float");
6962
varying_type->add_item("Int");
6963
varying_type->add_item("UInt");
6964
varying_type->add_item("Vector2");
6965
varying_type->add_item("Vector3");
6966
varying_type->add_item("Vector4");
6967
varying_type->add_item("Boolean");
6968
varying_type->add_item("Transform");
6969
varying_type->set_accessibility_name(TTRC("Varying Type"));
6970
varying_type->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_type_changed));
6971
6972
varying_name = memnew(LineEdit);
6973
hb->add_child(varying_name);
6974
varying_name->set_custom_minimum_size(Size2(150 * EDSCALE, 0));
6975
varying_name->set_h_size_flags(SIZE_EXPAND_FILL);
6976
varying_name->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_varying_name_changed));
6977
add_varying_dialog->register_text_enter(varying_name);
6978
6979
varying_mode = memnew(OptionButton);
6980
hb->add_child(varying_mode);
6981
varying_mode->add_item("Vertex -> [Fragment, Light]");
6982
varying_mode->add_item("Fragment -> Light");
6983
varying_mode->set_accessibility_name(TTRC("Varying Mode"));
6984
varying_mode->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_mode_changed));
6985
6986
varying_error_label = memnew(Label);
6987
varying_error_label->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
6988
vb->add_child(varying_error_label);
6989
varying_error_label->set_h_size_flags(SIZE_EXPAND_FILL);
6990
6991
varying_error_label->hide();
6992
}
6993
6994
// remove varying dialog
6995
{
6996
remove_varying_dialog = memnew(ConfirmationDialog);
6997
remove_varying_dialog->set_title(TTR("Delete Shader Varying"));
6998
remove_varying_dialog->set_ok_button_text(TTR("Delete"));
6999
remove_varying_dialog->connect(SceneStringName(confirmed), callable_mp(this, &VisualShaderEditor::_varying_deleted));
7000
add_child(remove_varying_dialog);
7001
7002
VBoxContainer *vb = memnew(VBoxContainer);
7003
remove_varying_dialog->add_child(vb);
7004
7005
varyings = memnew(Tree);
7006
vb->add_child(varyings);
7007
varyings->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7008
varyings->set_h_size_flags(SIZE_EXPAND_FILL);
7009
varyings->set_v_size_flags(SIZE_EXPAND_FILL);
7010
varyings->set_hide_root(true);
7011
varyings->set_allow_reselect(true);
7012
varyings->set_hide_folding(false);
7013
varyings->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
7014
varyings->connect("item_activated", callable_mp(this, &VisualShaderEditor::_varying_deleted));
7015
varyings->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_varying_selected));
7016
varyings->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_varying_unselected));
7017
}
7018
7019
alert = memnew(AcceptDialog);
7020
alert->get_label()->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
7021
alert->get_label()->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
7022
alert->get_label()->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
7023
alert->get_label()->set_custom_minimum_size(Size2(400, 60) * EDSCALE);
7024
add_child(alert);
7025
7026
frame_title_change_popup = memnew(PopupPanel);
7027
frame_title_change_edit = memnew(LineEdit);
7028
frame_title_change_edit->set_expand_to_text_length_enabled(true);
7029
frame_title_change_edit->set_select_all_on_focus(true);
7030
frame_title_change_edit->connect(SceneStringName(text_changed), callable_mp(this, &VisualShaderEditor::_frame_title_text_changed));
7031
frame_title_change_edit->connect(SceneStringName(text_submitted), callable_mp(this, &VisualShaderEditor::_frame_title_text_submitted));
7032
frame_title_change_popup->add_child(frame_title_change_edit);
7033
frame_title_change_edit->reset_size();
7034
frame_title_change_popup->reset_size();
7035
frame_title_change_popup->connect(SceneStringName(focus_exited), callable_mp(this, &VisualShaderEditor::_frame_title_popup_focus_out));
7036
frame_title_change_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_frame_title_popup_hide));
7037
add_child(frame_title_change_popup);
7038
7039
frame_tint_color_pick_popup = memnew(PopupPanel);
7040
VBoxContainer *frame_popup_item_tint_color_editor = memnew(VBoxContainer);
7041
frame_tint_color_pick_popup->add_child(frame_popup_item_tint_color_editor);
7042
frame_tint_color_picker = memnew(ColorPicker);
7043
frame_popup_item_tint_color_editor->add_child(frame_tint_color_picker);
7044
frame_tint_color_picker->reset_size();
7045
frame_tint_color_picker->connect("color_changed", callable_mp(this, &VisualShaderEditor::_frame_color_changed));
7046
Button *frame_tint_color_confirm_button = memnew(Button);
7047
frame_tint_color_confirm_button->set_text(TTR("OK"));
7048
frame_popup_item_tint_color_editor->add_child(frame_tint_color_confirm_button);
7049
frame_tint_color_confirm_button->connect(SceneStringName(pressed), callable_mp(this, &VisualShaderEditor::_frame_color_confirm));
7050
7051
frame_tint_color_pick_popup->connect("popup_hide", callable_mp(this, &VisualShaderEditor::_frame_color_popup_hide));
7052
add_child(frame_tint_color_pick_popup);
7053
7054
///////////////////////////////////////
7055
// SHADER NODES TREE OPTIONS
7056
///////////////////////////////////////
7057
7058
// COLOR
7059
7060
add_options.push_back(AddOption("ColorFunc", "Color/Common", "VisualShaderNodeColorFunc", TTR("Color function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7061
add_options.push_back(AddOption("ColorOp", "Color/Common", "VisualShaderNodeColorOp", TTR("Color operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7062
7063
add_options.push_back(AddOption("Grayscale", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7064
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));
7065
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));
7066
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));
7067
add_options.push_back(AddOption("Sepia", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7068
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));
7069
7070
add_options.push_back(AddOption("Burn", "Color/Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7071
add_options.push_back(AddOption("Darken", "Color/Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), { VisualShaderNodeColorOp::OP_DARKEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7072
add_options.push_back(AddOption("Difference", "Color/Operators", "VisualShaderNodeColorOp", TTR("Difference operator."), { VisualShaderNodeColorOp::OP_DIFFERENCE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7073
add_options.push_back(AddOption("Dodge", "Color/Operators", "VisualShaderNodeColorOp", TTR("Dodge operator."), { VisualShaderNodeColorOp::OP_DODGE }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7074
add_options.push_back(AddOption("HardLight", "Color/Operators", "VisualShaderNodeColorOp", TTR("HardLight operator."), { VisualShaderNodeColorOp::OP_HARD_LIGHT }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7075
add_options.push_back(AddOption("Lighten", "Color/Operators", "VisualShaderNodeColorOp", TTR("Lighten operator."), { VisualShaderNodeColorOp::OP_LIGHTEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7076
add_options.push_back(AddOption("Overlay", "Color/Operators", "VisualShaderNodeColorOp", TTR("Overlay operator."), { VisualShaderNodeColorOp::OP_OVERLAY }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7077
add_options.push_back(AddOption("Screen", "Color/Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), { VisualShaderNodeColorOp::OP_SCREEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7078
add_options.push_back(AddOption("SoftLight", "Color/Operators", "VisualShaderNodeColorOp", TTR("SoftLight operator."), { VisualShaderNodeColorOp::OP_SOFT_LIGHT }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7079
7080
add_options.push_back(AddOption("ColorConstant", "Color/Variables", "VisualShaderNodeColorConstant", TTR("Color constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7081
add_options.push_back(AddOption("ColorParameter", "Color/Variables", "VisualShaderNodeColorParameter", TTR("Color parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7082
7083
// COMMON
7084
7085
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));
7086
add_options.push_back(AddOption("DerivativeFunc", "Common", "VisualShaderNodeDerivativeFunc", TTR("Derivative function."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY, true));
7087
7088
// CONDITIONAL
7089
7090
const String &compare_func_desc = TTR("Returns the boolean result of the %s comparison between two parameters.");
7091
7092
add_options.push_back(AddOption("Equal (==)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Equal (==)")), { VisualShaderNodeCompare::FUNC_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7093
add_options.push_back(AddOption("GreaterThan (>)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Greater Than (>)")), { VisualShaderNodeCompare::FUNC_GREATER_THAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7094
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));
7095
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));
7096
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));
7097
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));
7098
add_options.push_back(AddOption("LessThan (<)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Less Than (<)")), { VisualShaderNodeCompare::FUNC_LESS_THAN }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7099
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));
7100
add_options.push_back(AddOption("NotEqual (!=)", "Conditional/Functions", "VisualShaderNodeCompare", vformat(compare_func_desc, TTR("Not Equal (!=)")), { VisualShaderNodeCompare::FUNC_NOT_EQUAL }, VisualShaderNode::PORT_TYPE_BOOLEAN));
7101
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));
7102
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));
7103
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));
7104
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));
7105
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));
7106
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));
7107
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));
7108
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));
7109
7110
add_options.push_back(AddOption("Compare (==)", "Conditional/Common", "VisualShaderNodeCompare", TTR("Returns the boolean result of the comparison between two parameters."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7111
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));
7112
7113
add_options.push_back(AddOption("BooleanConstant", "Conditional/Variables", "VisualShaderNodeBooleanConstant", TTR("Boolean constant."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7114
add_options.push_back(AddOption("BooleanParameter", "Conditional/Variables", "VisualShaderNodeBooleanParameter", TTR("Boolean parameter."), {}, VisualShaderNode::PORT_TYPE_BOOLEAN));
7115
7116
// INPUT
7117
7118
const String translation_gdsl = "\n\n" + TTR("Translated to '%s' in Godot Shading Language.");
7119
const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes.") + translation_gdsl;
7120
7121
// NODE3D-FOR-ALL
7122
7123
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));
7124
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));
7125
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));
7126
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));
7127
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));
7128
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));
7129
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));
7130
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));
7131
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));
7132
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));
7133
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));
7134
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));
7135
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));
7136
7137
// CANVASITEM-FOR-ALL
7138
7139
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));
7140
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));
7141
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));
7142
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));
7143
7144
// PARTICLES-FOR-ALL
7145
7146
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));
7147
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));
7148
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));
7149
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));
7150
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));
7151
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));
7152
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));
7153
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));
7154
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));
7155
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));
7156
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));
7157
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));
7158
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));
7159
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));
7160
7161
/////////////////
7162
7163
add_options.push_back(AddOption("Input", "Input/Common", "VisualShaderNodeInput", TTR("Input parameter.")));
7164
7165
const String input_param_for_vertex_and_fragment_shader_modes = TTR("'%s' input parameter for vertex and fragment shader modes.") + translation_gdsl;
7166
const String input_param_for_fragment_and_light_shader_modes = TTR("'%s' input parameter for fragment and light shader modes.") + translation_gdsl;
7167
const String input_param_for_fragment_shader_mode = TTR("'%s' input parameter for fragment shader mode.") + translation_gdsl;
7168
const String input_param_for_sky_shader_mode = TTR("'%s' input parameter for sky shader mode.") + translation_gdsl;
7169
const String input_param_for_fog_shader_mode = TTR("'%s' input parameter for fog shader mode.") + translation_gdsl;
7170
const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode.") + translation_gdsl;
7171
const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode.") + translation_gdsl;
7172
const String input_param_for_start_shader_mode = TTR("'%s' input parameter for start shader mode.") + translation_gdsl;
7173
const String input_param_for_process_shader_mode = TTR("'%s' input parameter for process shader mode.") + translation_gdsl;
7174
const String input_param_for_collide_shader_mode = TTR("'%s' input parameter for collide shader mode." + translation_gdsl);
7175
const String input_param_for_start_and_process_shader_mode = TTR("'%s' input parameter for start and process shader modes.") + translation_gdsl;
7176
const String input_param_for_process_and_collide_shader_mode = TTR("'%s' input parameter for process and collide shader modes.") + translation_gdsl;
7177
const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader modes.") + translation_gdsl;
7178
7179
// NODE3D INPUTS
7180
7181
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));
7182
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));
7183
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));
7184
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));
7185
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));
7186
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));
7187
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));
7188
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));
7189
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));
7190
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));
7191
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));
7192
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));
7193
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));
7194
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));
7195
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));
7196
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));
7197
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));
7198
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));
7199
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));
7200
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));
7201
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));
7202
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));
7203
7204
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));
7205
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));
7206
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));
7207
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));
7208
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));
7209
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));
7210
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));
7211
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));
7212
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));
7213
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));
7214
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));
7215
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));
7216
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));
7217
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));
7218
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));
7219
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));
7220
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));
7221
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));
7222
7223
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));
7224
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));
7225
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));
7226
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));
7227
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));
7228
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));
7229
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));
7230
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));
7231
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));
7232
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));
7233
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));
7234
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));
7235
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));
7236
7237
// CANVASITEM INPUTS
7238
7239
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));
7240
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));
7241
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));
7242
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));
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_CANVAS_ITEM));
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_CANVAS_ITEM));
7245
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));
7246
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));
7247
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));
7248
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));
7249
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));
7250
7251
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));
7252
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));
7253
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));
7254
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));
7255
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));
7256
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));
7257
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));
7258
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));
7259
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));
7260
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));
7261
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));
7262
7263
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));
7264
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));
7265
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));
7266
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));
7267
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));
7268
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));
7269
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));
7270
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));
7271
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));
7272
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));
7273
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));
7274
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));
7275
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));
7276
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));
7277
7278
// SKY INPUTS
7279
7280
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));
7281
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));
7282
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));
7283
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));
7284
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));
7285
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));
7286
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));
7287
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));
7288
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));
7289
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));
7290
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));
7291
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));
7292
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));
7293
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));
7294
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));
7295
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));
7296
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));
7297
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));
7298
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));
7299
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));
7300
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));
7301
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));
7302
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));
7303
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));
7304
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));
7305
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));
7306
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));
7307
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));
7308
7309
// FOG INPUTS
7310
7311
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));
7312
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));
7313
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));
7314
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));
7315
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));
7316
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));
7317
7318
// PARTICLES INPUTS
7319
7320
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));
7321
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));
7322
7323
// PARTICLES
7324
7325
add_options.push_back(AddOption("EmitParticle", "Particles", "VisualShaderNodeParticleEmit", "", {}, -1, TYPE_FLAGS_PROCESS | TYPE_FLAGS_PROCESS_CUSTOM | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7326
add_options.push_back(AddOption("ParticleAccelerator", "Particles", "VisualShaderNodeParticleAccelerator", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES));
7327
add_options.push_back(AddOption("ParticleRandomness", "Particles", "VisualShaderNodeParticleRandomness", "", {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT | TYPE_FLAGS_PROCESS | TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
7328
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));
7329
7330
add_options.push_back(AddOption("BoxEmitter", "Particles/Emitters", "VisualShaderNodeParticleBoxEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7331
7332
mesh_emitter_option_idx = add_options.size();
7333
add_options.push_back(AddOption("MeshEmitter", "Particles/Emitters", "VisualShaderNodeParticleMeshEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7334
7335
add_options.push_back(AddOption("RingEmitter", "Particles/Emitters", "VisualShaderNodeParticleRingEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7336
add_options.push_back(AddOption("SphereEmitter", "Particles/Emitters", "VisualShaderNodeParticleSphereEmitter", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7337
7338
add_options.push_back(AddOption("ConeVelocity", "Particles/Velocity", "VisualShaderNodeParticleConeVelocity", "", {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES));
7339
7340
// SCALAR
7341
7342
add_options.push_back(AddOption("FloatFunc", "Scalar/Common", "VisualShaderNodeFloatFunc", TTR("Float function."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7343
add_options.push_back(AddOption("FloatOp", "Scalar/Common", "VisualShaderNodeFloatOp", TTR("Float operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7344
add_options.push_back(AddOption("IntFunc", "Scalar/Common", "VisualShaderNodeIntFunc", TTR("Integer function."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7345
add_options.push_back(AddOption("IntOp", "Scalar/Common", "VisualShaderNodeIntOp", TTR("Integer operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7346
add_options.push_back(AddOption("UIntFunc", "Scalar/Common", "VisualShaderNodeUIntFunc", TTR("Unsigned integer function."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7347
add_options.push_back(AddOption("UIntOp", "Scalar/Common", "VisualShaderNodeUIntOp", TTR("Unsigned integer operator."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7348
7349
// CONSTANTS
7350
7351
for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) {
7352
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));
7353
}
7354
// FUNCTIONS
7355
7356
add_options.push_back(AddOption("Abs", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ABS }, VisualShaderNode::PORT_TYPE_SCALAR));
7357
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));
7358
add_options.push_back(AddOption("ACos", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ACOS }, VisualShaderNode::PORT_TYPE_SCALAR));
7359
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));
7360
add_options.push_back(AddOption("ASin", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ASIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7361
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));
7362
add_options.push_back(AddOption("ATan", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_ATAN }, VisualShaderNode::PORT_TYPE_SCALAR));
7363
add_options.push_back(AddOption("ATan2", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeFloatOp::OP_ATAN2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7364
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));
7365
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));
7366
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));
7367
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));
7368
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));
7369
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));
7370
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));
7371
add_options.push_back(AddOption("Cos", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_COS }, VisualShaderNode::PORT_TYPE_SCALAR));
7372
add_options.push_back(AddOption("CosH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_COSH }, VisualShaderNode::PORT_TYPE_SCALAR));
7373
add_options.push_back(AddOption("Degrees", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeFloatFunc::FUNC_DEGREES }, VisualShaderNode::PORT_TYPE_SCALAR));
7374
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));
7375
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));
7376
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));
7377
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));
7378
add_options.push_back(AddOption("Exp", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-e Exponential."), { VisualShaderNodeFloatFunc::FUNC_EXP }, VisualShaderNode::PORT_TYPE_SCALAR));
7379
add_options.push_back(AddOption("Exp2", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-2 Exponential."), { VisualShaderNodeFloatFunc::FUNC_EXP2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7380
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));
7381
add_options.push_back(AddOption("Fract", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeFloatFunc::FUNC_FRACT }, VisualShaderNode::PORT_TYPE_SCALAR));
7382
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));
7383
add_options.push_back(AddOption("Log", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Natural logarithm."), { VisualShaderNodeFloatFunc::FUNC_LOG }, VisualShaderNode::PORT_TYPE_SCALAR));
7384
add_options.push_back(AddOption("Log2", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Base-2 logarithm."), { VisualShaderNodeFloatFunc::FUNC_LOG2 }, VisualShaderNode::PORT_TYPE_SCALAR));
7385
add_options.push_back(AddOption("Max", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the greater of two values."), { VisualShaderNodeFloatOp::OP_MAX }, VisualShaderNode::PORT_TYPE_SCALAR));
7386
add_options.push_back(AddOption("Min", "Scalar/Functions", "VisualShaderNodeFloatOp", TTR("Returns the lesser of two values."), { VisualShaderNodeFloatOp::OP_MIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7387
add_options.push_back(AddOption("Mix", "Scalar/Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two scalars."), { VisualShaderNodeMix::OP_TYPE_SCALAR }, VisualShaderNode::PORT_TYPE_SCALAR));
7388
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));
7389
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));
7390
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));
7391
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));
7392
add_options.push_back(AddOption("OneMinus (1-)", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("1.0 - scalar"), { VisualShaderNodeFloatFunc::FUNC_ONEMINUS }, VisualShaderNode::PORT_TYPE_SCALAR));
7393
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));
7394
add_options.push_back(AddOption("Radians", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeFloatFunc::FUNC_RADIANS }, VisualShaderNode::PORT_TYPE_SCALAR));
7395
add_options.push_back(AddOption("Reciprocal", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("1.0 / scalar"), { VisualShaderNodeFloatFunc::FUNC_RECIPROCAL }, VisualShaderNode::PORT_TYPE_SCALAR));
7396
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));
7397
add_options.push_back(AddOption("Round", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeFloatFunc::FUNC_ROUND }, VisualShaderNode::PORT_TYPE_SCALAR));
7398
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));
7399
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));
7400
add_options.push_back(AddOption("Sign", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SIGN }, VisualShaderNode::PORT_TYPE_SCALAR));
7401
add_options.push_back(AddOption("Sign", "Scalar/Functions", "VisualShaderNodeIntFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeIntFunc::FUNC_SIGN }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7402
add_options.push_back(AddOption("Sin", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SIN }, VisualShaderNode::PORT_TYPE_SCALAR));
7403
add_options.push_back(AddOption("SinH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SINH }, VisualShaderNode::PORT_TYPE_SCALAR));
7404
add_options.push_back(AddOption("Sqrt", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeFloatFunc::FUNC_SQRT }, VisualShaderNode::PORT_TYPE_SCALAR));
7405
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));
7406
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));
7407
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));
7408
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));
7409
add_options.push_back(AddOption("Tan", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TAN }, VisualShaderNode::PORT_TYPE_SCALAR));
7410
add_options.push_back(AddOption("TanH", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TANH }, VisualShaderNode::PORT_TYPE_SCALAR));
7411
add_options.push_back(AddOption("Trunc", "Scalar/Functions", "VisualShaderNodeFloatFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeFloatFunc::FUNC_TRUNC }, VisualShaderNode::PORT_TYPE_SCALAR));
7412
7413
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Sums two floating-point scalars."), { VisualShaderNodeFloatOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR));
7414
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Sums two integer scalars."), { VisualShaderNodeIntOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7415
add_options.push_back(AddOption("Add (+)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Sums two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_ADD }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7416
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));
7417
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));
7418
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));
7419
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));
7420
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));
7421
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));
7422
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));
7423
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));
7424
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));
7425
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));
7426
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Divides two floating-point scalars."), { VisualShaderNodeFloatOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR));
7427
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Divides two integer scalars."), { VisualShaderNodeIntOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7428
add_options.push_back(AddOption("Divide (/)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Divides two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_DIV }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7429
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Multiplies two floating-point scalars."), { VisualShaderNodeFloatOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR));
7430
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Multiplies two integer scalars."), { VisualShaderNodeIntOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7431
add_options.push_back(AddOption("Multiply (*)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Multiplies two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_MUL }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7432
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));
7433
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));
7434
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));
7435
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeFloatOp", TTR("Subtracts two floating-point scalars."), { VisualShaderNodeFloatOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR));
7436
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeIntOp", TTR("Subtracts two integer scalars."), { VisualShaderNodeIntOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7437
add_options.push_back(AddOption("Subtract (-)", "Scalar/Operators", "VisualShaderNodeUIntOp", TTR("Subtracts two unsigned integer scalars."), { VisualShaderNodeUIntOp::OP_SUB }, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7438
7439
add_options.push_back(AddOption("FloatConstant", "Scalar/Variables", "VisualShaderNodeFloatConstant", TTR("Scalar floating-point constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7440
add_options.push_back(AddOption("IntConstant", "Scalar/Variables", "VisualShaderNodeIntConstant", TTR("Scalar integer constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7441
add_options.push_back(AddOption("UIntConstant", "Scalar/Variables", "VisualShaderNodeUIntConstant", TTR("Scalar unsigned integer constant."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7442
add_options.push_back(AddOption("FloatParameter", "Scalar/Variables", "VisualShaderNodeFloatParameter", TTR("Scalar floating-point parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7443
add_options.push_back(AddOption("IntParameter", "Scalar/Variables", "VisualShaderNodeIntParameter", TTR("Scalar integer parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR_INT));
7444
add_options.push_back(AddOption("UIntParameter", "Scalar/Variables", "VisualShaderNodeUIntParameter", TTR("Scalar unsigned integer parameter."), {}, VisualShaderNode::PORT_TYPE_SCALAR_UINT));
7445
7446
// SDF
7447
{
7448
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));
7449
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));
7450
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));
7451
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));
7452
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));
7453
}
7454
7455
// TEXTURES
7456
7457
add_options.push_back(AddOption("UVFunc", "Textures/Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7458
add_options.push_back(AddOption("UVPolarCoord", "Textures/Common", "VisualShaderNodeUVPolarCoord", TTR("Polar coordinates conversion applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7459
7460
cubemap_node_option_idx = add_options.size();
7461
add_options.push_back(AddOption("CubeMap", "Textures/Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7462
curve_node_option_idx = add_options.size();
7463
add_options.push_back(AddOption("CurveTexture", "Textures/Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7464
curve_xyz_node_option_idx = add_options.size();
7465
add_options.push_back(AddOption("CurveXYZTexture", "Textures/Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7466
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));
7467
texture2d_node_option_idx = add_options.size();
7468
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));
7469
texture2d_node_option_idx = add_options.size();
7470
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));
7471
texture2d_node_option_idx = add_options.size();
7472
add_options.push_back(AddOption("Texture2D", "Textures/Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7473
texture2d_array_node_option_idx = add_options.size();
7474
add_options.push_back(AddOption("Texture2DArray", "Textures/Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7475
texture3d_node_option_idx = add_options.size();
7476
add_options.push_back(AddOption("Texture3D", "Textures/Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7477
add_options.push_back(AddOption("UVPanning", "Textures/Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_PANNING }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7478
add_options.push_back(AddOption("UVScaling", "Textures/Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), { VisualShaderNodeUVFunc::FUNC_SCALING }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7479
7480
add_options.push_back(AddOption("CubeMapParameter", "Textures/Variables", "VisualShaderNodeCubemapParameter", TTR("Cubic texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7481
add_options.push_back(AddOption("Texture2DParameter", "Textures/Variables", "VisualShaderNodeTexture2DParameter", TTR("2D texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7482
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));
7483
add_options.push_back(AddOption("Texture2DArrayParameter", "Textures/Variables", "VisualShaderNodeTexture2DArrayParameter", TTR("2D array of textures parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7484
add_options.push_back(AddOption("Texture3DParameter", "Textures/Variables", "VisualShaderNodeTexture3DParameter", TTR("3D texture parameter lookup."), {}, VisualShaderNode::PORT_TYPE_SAMPLER));
7485
7486
// TRANSFORM
7487
7488
add_options.push_back(AddOption("TransformFunc", "Transform/Common", "VisualShaderNodeTransformFunc", TTR("Transform function."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7489
add_options.push_back(AddOption("TransformOp", "Transform/Common", "VisualShaderNodeTransformOp", TTR("Transform operator."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7490
7491
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));
7492
add_options.push_back(AddOption("TransformCompose", "Transform/Composition", "VisualShaderNodeTransformCompose", TTR("Composes transform from four vectors."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7493
add_options.push_back(AddOption("TransformDecompose", "Transform/Composition", "VisualShaderNodeTransformDecompose", TTR("Decomposes transform to four vectors.")));
7494
7495
add_options.push_back(AddOption("Determinant", "Transform/Functions", "VisualShaderNodeDeterminant", TTR("Calculates the determinant of a transform."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7496
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));
7497
add_options.push_back(AddOption("Inverse", "Transform/Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), { VisualShaderNodeTransformFunc::FUNC_INVERSE }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7498
add_options.push_back(AddOption("Transpose", "Transform/Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), { VisualShaderNodeTransformFunc::FUNC_TRANSPOSE }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7499
7500
add_options.push_back(AddOption("Add (+)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Sums two transforms."), { VisualShaderNodeTransformOp::OP_ADD }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7501
add_options.push_back(AddOption("Divide (/)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Divides two transforms."), { VisualShaderNodeTransformOp::OP_A_DIV_B }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7502
add_options.push_back(AddOption("Multiply (*)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Multiplies two transforms."), { VisualShaderNodeTransformOp::OP_AxB }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7503
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));
7504
add_options.push_back(AddOption("Subtract (-)", "Transform/Operators", "VisualShaderNodeTransformOp", TTR("Subtracts two transforms."), { VisualShaderNodeTransformOp::OP_A_MINUS_B }, VisualShaderNode::PORT_TYPE_TRANSFORM));
7505
add_options.push_back(AddOption("TransformVectorMult (*)", "Transform/Operators", "VisualShaderNodeTransformVecMult", TTR("Multiplies vector by transform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7506
7507
add_options.push_back(AddOption("TransformConstant", "Transform/Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7508
add_options.push_back(AddOption("TransformParameter", "Transform/Variables", "VisualShaderNodeTransformParameter", TTR("Transform parameter."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM));
7509
7510
// UTILITY
7511
7512
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));
7513
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));
7514
add_options.push_back(AddOption("RandomRange", "Utility", "VisualShaderNodeRandomRange", TTR("Returns a random value between the minimum and maximum input values."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7515
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));
7516
7517
// VECTOR
7518
7519
add_options.push_back(AddOption("VectorFunc", "Vector/Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7520
add_options.push_back(AddOption("VectorOp", "Vector/Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7521
add_options.push_back(AddOption("VectorCompose", "Vector/Common", "VisualShaderNodeVectorCompose", TTR("Composes vector from scalars.")));
7522
add_options.push_back(AddOption("VectorDecompose", "Vector/Common", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to scalars.")));
7523
7524
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));
7525
add_options.push_back(AddOption("Vector2Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 2D vector to two scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_2D }));
7526
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));
7527
add_options.push_back(AddOption("Vector3Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 3D vector to three scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_3D }));
7528
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));
7529
add_options.push_back(AddOption("Vector4Decompose", "Vector/Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 4D vector to four scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_4D }));
7530
7531
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));
7532
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));
7533
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));
7534
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));
7535
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));
7536
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));
7537
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));
7538
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));
7539
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));
7540
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));
7541
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));
7542
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));
7543
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));
7544
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));
7545
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));
7546
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));
7547
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));
7548
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));
7549
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));
7550
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));
7551
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));
7552
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));
7553
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));
7554
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));
7555
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));
7556
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));
7557
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));
7558
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));
7559
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));
7560
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));
7561
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));
7562
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));
7563
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));
7564
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));
7565
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));
7566
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));
7567
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));
7568
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));
7569
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));
7570
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));
7571
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));
7572
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));
7573
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));
7574
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));
7575
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));
7576
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));
7577
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));
7578
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));
7579
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));
7580
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));
7581
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));
7582
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));
7583
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));
7584
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));
7585
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));
7586
add_options.push_back(AddOption("Dot", "Vector/Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
7587
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));
7588
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));
7589
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));
7590
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));
7591
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));
7592
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));
7593
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));
7594
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));
7595
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));
7596
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));
7597
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));
7598
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));
7599
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));
7600
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));
7601
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));
7602
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));
7603
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));
7604
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));
7605
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));
7606
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));
7607
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));
7608
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));
7609
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));
7610
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));
7611
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));
7612
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));
7613
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));
7614
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));
7615
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));
7616
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));
7617
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));
7618
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));
7619
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));
7620
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));
7621
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));
7622
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));
7623
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));
7624
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));
7625
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));
7626
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));
7627
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));
7628
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));
7629
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));
7630
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));
7631
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));
7632
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));
7633
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));
7634
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));
7635
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));
7636
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));
7637
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));
7638
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));
7639
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));
7640
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));
7641
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));
7642
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));
7643
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));
7644
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));
7645
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));
7646
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));
7647
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));
7648
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));
7649
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));
7650
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));
7651
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7652
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7653
add_options.push_back(AddOption("Refract", "Vector/Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7654
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));
7655
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));
7656
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));
7657
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));
7658
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));
7659
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));
7660
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));
7661
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));
7662
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));
7663
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));
7664
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));
7665
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));
7666
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));
7667
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));
7668
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));
7669
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));
7670
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));
7671
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));
7672
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));
7673
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));
7674
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));
7675
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));
7676
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));
7677
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));
7678
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));
7679
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));
7680
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));
7681
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));
7682
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));
7683
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));
7684
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));
7685
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));
7686
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));
7687
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));
7688
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));
7689
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));
7690
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));
7691
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));
7692
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));
7693
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));
7694
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));
7695
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));
7696
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));
7697
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));
7698
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));
7699
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));
7700
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));
7701
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));
7702
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));
7703
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));
7704
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));
7705
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));
7706
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));
7707
7708
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));
7709
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));
7710
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));
7711
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));
7712
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));
7713
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));
7714
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));
7715
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));
7716
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));
7717
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));
7718
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));
7719
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));
7720
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));
7721
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));
7722
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));
7723
7724
add_options.push_back(AddOption("Vector2Constant", "Vector/Variables", "VisualShaderNodeVec2Constant", TTR("2D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7725
add_options.push_back(AddOption("Vector2Parameter", "Vector/Variables", "VisualShaderNodeVec2Parameter", TTR("2D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
7726
add_options.push_back(AddOption("Vector3Constant", "Vector/Variables", "VisualShaderNodeVec3Constant", TTR("3D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7727
add_options.push_back(AddOption("Vector3Parameter", "Vector/Variables", "VisualShaderNodeVec3Parameter", TTR("3D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
7728
add_options.push_back(AddOption("Vector4Constant", "Vector/Variables", "VisualShaderNodeVec4Constant", TTR("4D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7729
add_options.push_back(AddOption("Vector4Parameter", "Vector/Variables", "VisualShaderNodeVec4Parameter", TTR("4D vector parameter."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
7730
7731
// SPECIAL
7732
add_options.push_back(AddOption("Frame", "Special", "VisualShaderNodeFrame", TTR("A rectangular area with a description string for better graph organization.")));
7733
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.")));
7734
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.")));
7735
add_options.push_back(AddOption("ParameterRef", "Special", "VisualShaderNodeParameterRef", TTR("A reference to an existing parameter.")));
7736
add_options.push_back(AddOption("VaryingGetter", "Special", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
7737
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
7738
add_options.push_back(AddOption("VaryingGetter", "Special", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
7739
add_options.push_back(AddOption("VaryingSetter", "Special", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
7740
add_options.push_back(AddOption("Reroute", "Special", "VisualShaderNodeReroute", TTR("Reroute connections freely, can be used to connect multiple input ports to single output port.")));
7741
7742
custom_node_option_idx = add_options.size();
7743
7744
/////////////////////////////////////////////////////////////////////
7745
7746
Ref<VisualShaderNodePluginDefault> default_plugin;
7747
default_plugin.instantiate();
7748
default_plugin->set_editor(this);
7749
add_plugin(default_plugin);
7750
7751
graph_plugin.instantiate();
7752
graph_plugin->set_editor(this);
7753
7754
property_editor_popup = memnew(PopupPanel);
7755
property_editor_popup->set_min_size(Size2(360, 0) * EDSCALE);
7756
add_child(property_editor_popup);
7757
7758
edited_property_holder.instantiate();
7759
7760
panning_debounce_timer = memnew(Timer);
7761
panning_debounce_timer->set_one_shot(true);
7762
panning_debounce_timer->set_wait_time(1.0);
7763
panning_debounce_timer->connect("timeout", callable_mp(this, &VisualShaderEditor::save_editor_layout));
7764
add_child(panning_debounce_timer);
7765
}
7766
7767
VisualShaderEditor::~VisualShaderEditor() {
7768
save_editor_layout();
7769
}
7770
7771
class VisualShaderNodePluginInputEditor : public OptionButton {
7772
GDCLASS(VisualShaderNodePluginInputEditor, OptionButton);
7773
7774
VisualShaderEditor *editor = nullptr;
7775
Ref<VisualShaderNodeInput> input;
7776
7777
public:
7778
void _notification(int p_what) {
7779
switch (p_what) {
7780
case NOTIFICATION_READY: {
7781
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginInputEditor::_item_selected));
7782
} break;
7783
}
7784
}
7785
7786
void _item_selected(int p_item) {
7787
editor->call_deferred(SNAME("_input_select_item"), input, get_item_metadata(p_item));
7788
}
7789
7790
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeInput> &p_input) {
7791
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7792
7793
editor = p_editor;
7794
input = p_input;
7795
7796
Ref<Texture2D> type_icon[] = {
7797
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7798
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
7799
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
7800
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
7801
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
7802
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
7803
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
7804
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
7805
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("ImageTexture"), EditorStringName(EditorIcons)),
7806
};
7807
7808
add_item(TTR("[None]"));
7809
set_item_metadata(-1, "[None]");
7810
7811
int to_select = -1;
7812
for (int i = 0; i < input->get_input_index_count(); i++) {
7813
if (input->get_input_name() == input->get_input_index_name(i)) {
7814
to_select = i + 1;
7815
}
7816
add_icon_item(type_icon[input->get_input_index_type(i)], input->get_input_index_name(i));
7817
set_item_metadata(-1, input->get_input_index_name(i));
7818
}
7819
7820
if (to_select >= 0) {
7821
select(to_select);
7822
}
7823
}
7824
};
7825
7826
////////////////
7827
7828
class VisualShaderNodePluginVaryingEditor : public OptionButton {
7829
GDCLASS(VisualShaderNodePluginVaryingEditor, OptionButton);
7830
7831
VisualShaderEditor *editor = nullptr;
7832
Ref<VisualShaderNodeVarying> varying;
7833
7834
public:
7835
void _notification(int p_what) {
7836
if (p_what == NOTIFICATION_READY) {
7837
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginVaryingEditor::_item_selected));
7838
}
7839
}
7840
7841
void _item_selected(int p_item) {
7842
editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_metadata(p_item));
7843
}
7844
7845
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) {
7846
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7847
7848
editor = p_editor;
7849
varying = p_varying;
7850
7851
Ref<Texture2D> type_icon[] = {
7852
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7853
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
7854
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
7855
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
7856
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
7857
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
7858
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
7859
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
7860
};
7861
7862
bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
7863
7864
add_item(TTR("[None]"));
7865
set_item_metadata(-1, "[None]");
7866
7867
int to_select = -1;
7868
for (int i = 0, j = 0; i < varying->get_varyings_count(); i++) {
7869
VisualShader::VaryingMode mode = varying->get_varying_mode_by_index(i);
7870
if (is_getter) {
7871
if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
7872
if (p_type != VisualShader::TYPE_LIGHT) {
7873
j++;
7874
continue;
7875
}
7876
} else {
7877
if (p_type != VisualShader::TYPE_FRAGMENT && p_type != VisualShader::TYPE_LIGHT) {
7878
j++;
7879
continue;
7880
}
7881
}
7882
} else {
7883
if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
7884
if (p_type != VisualShader::TYPE_FRAGMENT) {
7885
j++;
7886
continue;
7887
}
7888
} else {
7889
if (p_type != VisualShader::TYPE_VERTEX) {
7890
j++;
7891
continue;
7892
}
7893
}
7894
}
7895
if (varying->get_varying_name() == varying->get_varying_name_by_index(i)) {
7896
to_select = i - j + 1;
7897
}
7898
add_icon_item(type_icon[varying->get_varying_type_by_index(i)], varying->get_varying_name_by_index(i));
7899
set_item_metadata(-1, varying->get_varying_name_by_index(i));
7900
}
7901
7902
if (to_select >= 0) {
7903
select(to_select);
7904
}
7905
}
7906
};
7907
7908
////////////////
7909
7910
class VisualShaderNodePluginParameterRefEditor : public OptionButton {
7911
GDCLASS(VisualShaderNodePluginParameterRefEditor, OptionButton);
7912
7913
VisualShaderEditor *editor = nullptr;
7914
Ref<VisualShaderNodeParameterRef> parameter_ref;
7915
7916
public:
7917
void _notification(int p_what) {
7918
switch (p_what) {
7919
case NOTIFICATION_READY: {
7920
connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderNodePluginParameterRefEditor::_item_selected));
7921
} break;
7922
}
7923
}
7924
7925
void _item_selected(int p_item) {
7926
editor->call_deferred(SNAME("_parameter_ref_select_item"), parameter_ref, get_item_metadata(p_item));
7927
}
7928
7929
void setup(VisualShaderEditor *p_editor, const Ref<VisualShaderNodeParameterRef> &p_parameter_ref) {
7930
set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
7931
7932
editor = p_editor;
7933
parameter_ref = p_parameter_ref;
7934
7935
Ref<Texture2D> type_icon[] = {
7936
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("float"), EditorStringName(EditorIcons)),
7937
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("int"), EditorStringName(EditorIcons)),
7938
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("uint"), EditorStringName(EditorIcons)),
7939
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("bool"), EditorStringName(EditorIcons)),
7940
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector2"), EditorStringName(EditorIcons)),
7941
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector3"), EditorStringName(EditorIcons)),
7942
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Vector4"), EditorStringName(EditorIcons)),
7943
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Transform3D"), EditorStringName(EditorIcons)),
7944
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Color"), EditorStringName(EditorIcons)),
7945
EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("ImageTexture"), EditorStringName(EditorIcons)),
7946
};
7947
7948
add_item(TTR("[None]"));
7949
set_item_metadata(-1, "[None]");
7950
7951
int to_select = -1;
7952
for (int i = 0; i < p_parameter_ref->get_parameters_count(); i++) {
7953
if (p_parameter_ref->get_parameter_name() == p_parameter_ref->get_parameter_name_by_index(i)) {
7954
to_select = i + 1;
7955
}
7956
add_icon_item(type_icon[p_parameter_ref->get_parameter_type_by_index(i)], p_parameter_ref->get_parameter_name_by_index(i));
7957
set_item_metadata(-1, p_parameter_ref->get_parameter_name_by_index(i));
7958
}
7959
7960
if (to_select >= 0) {
7961
select(to_select);
7962
}
7963
}
7964
};
7965
7966
////////////////
7967
7968
class VisualShaderNodePluginDefaultEditor : public VBoxContainer {
7969
GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer);
7970
VisualShaderEditor *editor = nullptr;
7971
Ref<Resource> parent_resource;
7972
int node_id = 0;
7973
VisualShader::Type shader_type;
7974
7975
public:
7976
void _property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false) {
7977
if (p_changing) {
7978
return;
7979
}
7980
7981
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
7982
7983
updating = true;
7984
undo_redo->create_action(vformat(TTR("Edit Visual Property: %s"), p_property), UndoRedo::MERGE_ENDS);
7985
undo_redo->add_do_property(node.ptr(), p_property, p_value);
7986
undo_redo->add_undo_property(node.ptr(), p_property, node->get(p_property));
7987
7988
Ref<VisualShaderNode> vsnode = editor->get_visual_shader()->get_node(shader_type, node_id);
7989
ERR_FAIL_COND(vsnode.is_null());
7990
7991
// Check for invalid connections due to removed ports.
7992
// We need to know the new state of the node to generate the proper undo/redo instructions.
7993
// Quite hacky but the best way I could come up with for now.
7994
Ref<VisualShaderNode> vsnode_new = vsnode->duplicate();
7995
vsnode_new->set(p_property, p_value);
7996
const int input_port_count = vsnode_new->get_input_port_count();
7997
const int output_port_count = vsnode_new->get_expanded_output_port_count();
7998
7999
List<VisualShader::Connection> conns;
8000
editor->get_visual_shader()->get_node_connections(shader_type, &conns);
8001
VisualShaderGraphPlugin *graph_plugin = editor->get_graph_plugin();
8002
bool undo_node_already_updated = false;
8003
for (const VisualShader::Connection &c : conns) {
8004
if ((c.from_node == node_id && c.from_port >= output_port_count) || (c.to_node == node_id && c.to_port >= input_port_count)) {
8005
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);
8006
undo_redo->add_do_method(graph_plugin, "disconnect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8007
// We need to update the node before reconnecting to avoid accessing a non-existing port.
8008
undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8009
undo_node_already_updated = true;
8010
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);
8011
undo_redo->add_undo_method(graph_plugin, "connect_nodes", shader_type, c.from_node, c.from_port, c.to_node, c.to_port);
8012
}
8013
}
8014
8015
if (p_value.get_type() == Variant::OBJECT) {
8016
Ref<Resource> prev_res = vsnode->get(p_property);
8017
Ref<Resource> curr_res = p_value;
8018
8019
if (curr_res.is_null()) {
8020
undo_redo->add_do_method(this, "_open_inspector", (Ref<Resource>)parent_resource.ptr());
8021
} else {
8022
undo_redo->add_do_method(this, "_open_inspector", (Ref<Resource>)curr_res.ptr());
8023
}
8024
if (prev_res.is_valid()) {
8025
undo_redo->add_undo_method(this, "_open_inspector", (Ref<Resource>)prev_res.ptr());
8026
} else {
8027
undo_redo->add_undo_method(this, "_open_inspector", (Ref<Resource>)parent_resource.ptr());
8028
}
8029
}
8030
if (p_property != "constant") {
8031
if (graph_plugin) {
8032
undo_redo->add_do_method(editor, "_update_next_previews", node_id);
8033
undo_redo->add_undo_method(editor, "_update_next_previews", node_id);
8034
undo_redo->add_do_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8035
if (!undo_node_already_updated) {
8036
undo_redo->add_undo_method(graph_plugin, "update_node_deferred", shader_type, node_id);
8037
}
8038
}
8039
}
8040
8041
undo_redo->commit_action();
8042
8043
updating = false;
8044
}
8045
8046
void _node_changed() {
8047
if (updating) {
8048
return;
8049
}
8050
for (int i = 0; i < properties.size(); i++) {
8051
properties[i]->update_property();
8052
}
8053
}
8054
8055
void _resource_selected(const String &p_path, Ref<Resource> p_resource) {
8056
_open_inspector(p_resource);
8057
}
8058
8059
void _open_inspector(Ref<Resource> p_resource) {
8060
InspectorDock::get_inspector_singleton()->edit(p_resource.ptr());
8061
}
8062
8063
bool updating = false;
8064
Ref<VisualShaderNode> node;
8065
Vector<EditorProperty *> properties;
8066
Vector<Label *> prop_names;
8067
8068
void _show_prop_names(bool p_show) {
8069
for (int i = 0; i < prop_names.size(); i++) {
8070
prop_names[i]->set_visible(p_show);
8071
}
8072
}
8073
8074
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) {
8075
editor = p_editor;
8076
parent_resource = p_parent_resource;
8077
updating = false;
8078
node = p_node;
8079
properties = p_properties;
8080
8081
node_id = (int)p_node->get_meta("id");
8082
shader_type = VisualShader::Type((int)p_node->get_meta("shader_type"));
8083
8084
for (int i = 0; i < p_properties.size(); i++) {
8085
HBoxContainer *hbox = memnew(HBoxContainer);
8086
hbox->set_h_size_flags(SIZE_EXPAND_FILL);
8087
add_child(hbox);
8088
8089
Label *prop_name = memnew(Label);
8090
prop_name->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
8091
String prop_name_str = p_names[i];
8092
if (p_overrided_names.has(p_names[i])) {
8093
prop_name_str = p_overrided_names[p_names[i]] + ":";
8094
} else {
8095
prop_name_str = prop_name_str.capitalize() + ":";
8096
}
8097
prop_name->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); // TODO: Implement proper translation switch.
8098
prop_name->set_text(prop_name_str);
8099
prop_name->set_visible(false);
8100
hbox->add_child(prop_name);
8101
prop_names.push_back(prop_name);
8102
8103
p_properties[i]->set_h_size_flags(SIZE_EXPAND_FILL);
8104
hbox->add_child(p_properties[i]);
8105
8106
bool res_prop = Object::cast_to<EditorPropertyResource>(p_properties[i]);
8107
if (res_prop) {
8108
p_properties[i]->connect("resource_selected", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_resource_selected));
8109
}
8110
8111
properties[i]->connect("property_changed", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_property_changed));
8112
properties[i]->set_object_and_property(node.ptr(), p_names[i]);
8113
properties[i]->update_property();
8114
properties[i]->set_name_split_ratio(0);
8115
}
8116
node->connect_changed(callable_mp(this, &VisualShaderNodePluginDefaultEditor::_node_changed));
8117
}
8118
8119
static void _bind_methods() {
8120
ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); // Used by UndoRedo.
8121
ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); // Used with call_deferred.
8122
}
8123
};
8124
8125
Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
8126
Ref<VisualShader> p_shader = Ref<VisualShader>(p_parent_resource.ptr());
8127
8128
if (p_shader.is_valid() && (p_node->is_class("VisualShaderNodeVaryingGetter") || p_node->is_class("VisualShaderNodeVaryingSetter"))) {
8129
VisualShaderNodePluginVaryingEditor *editor = memnew(VisualShaderNodePluginVaryingEditor);
8130
editor->setup(vseditor, p_node, vseditor->get_current_shader_type());
8131
return editor;
8132
}
8133
8134
if (p_node->is_class("VisualShaderNodeParameterRef")) {
8135
VisualShaderNodePluginParameterRefEditor *editor = memnew(VisualShaderNodePluginParameterRefEditor);
8136
editor->setup(vseditor, p_node);
8137
return editor;
8138
}
8139
8140
if (p_node->is_class("VisualShaderNodeInput")) {
8141
VisualShaderNodePluginInputEditor *editor = memnew(VisualShaderNodePluginInputEditor);
8142
editor->setup(vseditor, p_node);
8143
return editor;
8144
}
8145
8146
Vector<StringName> properties = p_node->get_editable_properties();
8147
if (properties.is_empty()) {
8148
return nullptr;
8149
}
8150
8151
List<PropertyInfo> props;
8152
p_node->get_property_list(&props);
8153
8154
Vector<PropertyInfo> pinfo;
8155
8156
for (const PropertyInfo &E : props) {
8157
for (int i = 0; i < properties.size(); i++) {
8158
if (E.name == String(properties[i])) {
8159
pinfo.push_back(E);
8160
}
8161
}
8162
}
8163
8164
if (pinfo.is_empty()) {
8165
return nullptr;
8166
}
8167
8168
properties.clear();
8169
8170
Ref<VisualShaderNode> node = p_node;
8171
Vector<EditorProperty *> editors;
8172
8173
for (int i = 0; i < pinfo.size(); i++) {
8174
EditorProperty *prop = EditorInspector::instantiate_property_editor(node.ptr(), pinfo[i].type, pinfo[i].name, pinfo[i].hint, pinfo[i].hint_string, pinfo[i].usage);
8175
if (!prop) {
8176
return nullptr;
8177
}
8178
8179
if (Object::cast_to<EditorPropertyResource>(prop)) {
8180
Object::cast_to<EditorPropertyResource>(prop)->set_use_sub_inspector(false);
8181
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8182
} else if (Object::cast_to<EditorPropertyTransform3D>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
8183
prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
8184
} else if (Object::cast_to<EditorPropertyVector4>(prop)) {
8185
prop->set_custom_minimum_size(Size2(320 * EDSCALE, 0));
8186
} else if (Object::cast_to<EditorPropertyFloat>(prop)) {
8187
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8188
} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
8189
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
8190
Object::cast_to<EditorPropertyEnum>(prop)->set_option_button_clip(false);
8191
} else if (Object::cast_to<EditorPropertyColor>(prop)) {
8192
Object::cast_to<EditorPropertyColor>(prop)->set_live_changes_enabled(false);
8193
}
8194
8195
editors.push_back(prop);
8196
properties.push_back(pinfo[i].name);
8197
}
8198
VisualShaderNodePluginDefaultEditor *editor = memnew(VisualShaderNodePluginDefaultEditor);
8199
editor->setup(vseditor, p_parent_resource, editors, properties, p_node->get_editable_properties_names(), p_node);
8200
return editor;
8201
}
8202
8203
void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
8204
Ref<VisualShader> visual_shader(Object::cast_to<VisualShader>(get_edited_object()));
8205
if (visual_shader->get_mode() == p_which) {
8206
return;
8207
}
8208
8209
ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_editor_data().get_editor_by_name("Shader"));
8210
if (!shader_editor) {
8211
return;
8212
}
8213
VisualShaderEditor *editor = Object::cast_to<VisualShaderEditor>(shader_editor->get_shader_editor(visual_shader));
8214
if (!editor) {
8215
return;
8216
}
8217
8218
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
8219
undo_redo->create_action(TTR("Visual Shader Mode Changed"));
8220
//do is easy
8221
undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which);
8222
undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode());
8223
8224
undo_redo->add_do_method(editor, "_set_mode", p_which);
8225
undo_redo->add_undo_method(editor, "_set_mode", visual_shader->get_mode());
8226
8227
//now undo is hell
8228
8229
//1. restore connections to output
8230
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
8231
VisualShader::Type type = VisualShader::Type(i);
8232
List<VisualShader::Connection> conns;
8233
visual_shader->get_node_connections(type, &conns);
8234
for (const VisualShader::Connection &E : conns) {
8235
if (E.to_node == VisualShader::NODE_ID_OUTPUT) {
8236
undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
8237
}
8238
}
8239
}
8240
//2. restore input indices
8241
for (int i = 0; i < VisualShader::TYPE_MAX; i++) {
8242
VisualShader::Type type = VisualShader::Type(i);
8243
Vector<int> nodes = visual_shader->get_node_list(type);
8244
for (int j = 0; j < nodes.size(); j++) {
8245
Ref<VisualShaderNodeInput> input = visual_shader->get_node(type, nodes[j]);
8246
if (input.is_null()) {
8247
continue;
8248
}
8249
8250
undo_redo->add_undo_method(input.ptr(), "set_input_name", input->get_input_name());
8251
}
8252
}
8253
8254
//3. restore enums and flags
8255
List<PropertyInfo> props;
8256
visual_shader->get_property_list(&props);
8257
8258
for (const PropertyInfo &E : props) {
8259
if (E.name.begins_with("flags/") || E.name.begins_with("modes/")) {
8260
undo_redo->add_undo_property(visual_shader.ptr(), E.name, visual_shader->get(E.name));
8261
}
8262
}
8263
8264
//4. delete varyings (if needed)
8265
if (p_which == VisualShader::MODE_PARTICLES || p_which == VisualShader::MODE_SKY || p_which == VisualShader::MODE_FOG) {
8266
int var_count = visual_shader->get_varyings_count();
8267
8268
if (var_count > 0) {
8269
for (int i = 0; i < var_count; i++) {
8270
const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
8271
undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", var->name);
8272
undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", var->name, var->mode, var->type);
8273
}
8274
8275
undo_redo->add_do_method(editor, "_update_varyings");
8276
undo_redo->add_undo_method(editor, "_update_varyings");
8277
}
8278
}
8279
8280
undo_redo->add_do_method(editor, "_update_nodes");
8281
undo_redo->add_undo_method(editor, "_update_nodes");
8282
8283
undo_redo->add_do_method(editor, "_update_graph");
8284
undo_redo->add_undo_method(editor, "_update_graph");
8285
8286
undo_redo->commit_action();
8287
}
8288
8289
void EditorPropertyVisualShaderMode::update_property() {
8290
int which = get_edited_property_value();
8291
options->select(which);
8292
}
8293
8294
void EditorPropertyVisualShaderMode::setup(const Vector<String> &p_options) {
8295
for (int i = 0; i < p_options.size(); i++) {
8296
options->add_item(p_options[i], i);
8297
}
8298
}
8299
8300
void EditorPropertyVisualShaderMode::set_option_button_clip(bool p_enable) {
8301
options->set_clip_text(p_enable);
8302
}
8303
8304
EditorPropertyVisualShaderMode::EditorPropertyVisualShaderMode() {
8305
options = memnew(OptionButton);
8306
options->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
8307
options->set_clip_text(true);
8308
add_child(options);
8309
add_focusable(options);
8310
options->connect(SceneStringName(item_selected), callable_mp(this, &EditorPropertyVisualShaderMode::_option_selected));
8311
}
8312
8313
bool EditorInspectorVisualShaderModePlugin::can_handle(Object *p_object) {
8314
return true; // Can handle everything.
8315
}
8316
8317
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) {
8318
if (p_path == "mode" && p_object->is_class("VisualShader") && p_type == Variant::INT) {
8319
EditorPropertyVisualShaderMode *mode_editor = memnew(EditorPropertyVisualShaderMode);
8320
Vector<String> options = p_hint_text.split(",");
8321
mode_editor->setup(options);
8322
add_property_editor(p_path, mode_editor);
8323
8324
return true;
8325
}
8326
8327
return false;
8328
}
8329
8330
//////////////////////////////////
8331
8332
void VisualShaderNodePortPreview::_shader_changed() {
8333
if (!is_valid || shader.is_null()) {
8334
return;
8335
}
8336
8337
Vector<VisualShader::DefaultTextureParam> default_textures;
8338
String shader_code = shader->generate_preview_shader(type, node, port, default_textures);
8339
8340
Ref<Shader> preview_shader;
8341
preview_shader.instantiate();
8342
preview_shader->set_code(shader_code);
8343
for (int i = 0; i < default_textures.size(); i++) {
8344
int j = 0;
8345
for (List<Ref<Texture>>::ConstIterator itr = default_textures[i].params.begin(); itr != default_textures[i].params.end(); ++itr, ++j) {
8346
preview_shader->set_default_texture_parameter(default_textures[i].name, *itr, j);
8347
}
8348
}
8349
8350
Ref<ShaderMaterial> mat;
8351
mat.instantiate();
8352
mat->set_shader(preview_shader);
8353
8354
if (preview_mat.is_valid() && preview_mat->get_shader().is_valid()) {
8355
List<PropertyInfo> params;
8356
preview_mat->get_shader()->get_shader_uniform_list(&params);
8357
for (const PropertyInfo &E : params) {
8358
mat->set_shader_parameter(E.name, preview_mat->get_shader_parameter(E.name));
8359
}
8360
}
8361
8362
set_material(mat);
8363
}
8364
8365
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) {
8366
if (p_has_transparency) {
8367
checkerboard = memnew(TextureRect);
8368
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
8369
checkerboard->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
8370
checkerboard->set_draw_behind_parent(true);
8371
add_child(checkerboard);
8372
}
8373
8374
set_mouse_filter(MOUSE_FILTER_PASS);
8375
shader = p_shader;
8376
shader->connect_changed(callable_mp(this, &VisualShaderNodePortPreview::_shader_changed), CONNECT_DEFERRED);
8377
preview_mat = p_preview_material;
8378
type = p_type;
8379
port = p_port;
8380
node = p_node;
8381
is_valid = p_is_valid;
8382
queue_redraw();
8383
_shader_changed();
8384
}
8385
8386
Size2 VisualShaderNodePortPreview::get_minimum_size() const {
8387
int port_preview_size = EDITOR_GET("editors/visual_editors/visual_shader/port_preview_size");
8388
return Size2(port_preview_size, port_preview_size) * EDSCALE;
8389
}
8390
8391
void VisualShaderNodePortPreview::_notification(int p_what) {
8392
switch (p_what) {
8393
case NOTIFICATION_THEME_CHANGED: {
8394
if (checkerboard != nullptr) {
8395
checkerboard->set_texture(get_theme_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
8396
}
8397
} break;
8398
case NOTIFICATION_DRAW: {
8399
Vector<Vector2> points = {
8400
Vector2(),
8401
Vector2(get_size().width, 0),
8402
get_size(),
8403
Vector2(0, get_size().height)
8404
};
8405
8406
Vector<Vector2> uvs = {
8407
Vector2(0, 0),
8408
Vector2(1, 0),
8409
Vector2(1, 1),
8410
Vector2(0, 1)
8411
};
8412
8413
if (is_valid) {
8414
Vector<Color> colors = {
8415
Color(1, 1, 1, 1),
8416
Color(1, 1, 1, 1),
8417
Color(1, 1, 1, 1),
8418
Color(1, 1, 1, 1)
8419
};
8420
draw_primitive(points, colors, uvs);
8421
} else {
8422
Vector<Color> colors = {
8423
Color(0, 0, 0, 1),
8424
Color(0, 0, 0, 1),
8425
Color(0, 0, 0, 1),
8426
Color(0, 0, 0, 1)
8427
};
8428
draw_primitive(points, colors, uvs);
8429
}
8430
8431
} break;
8432
}
8433
}
8434
8435
//////////////////////////////////
8436
8437
String VisualShaderConversionPlugin::converts_to() const {
8438
return "Shader";
8439
}
8440
8441
bool VisualShaderConversionPlugin::handles(const Ref<Resource> &p_resource) const {
8442
Ref<VisualShader> vshader = p_resource;
8443
return vshader.is_valid();
8444
}
8445
8446
Ref<Resource> VisualShaderConversionPlugin::convert(const Ref<Resource> &p_resource) const {
8447
Ref<VisualShader> vshader = p_resource;
8448
ERR_FAIL_COND_V(vshader.is_null(), Ref<Resource>());
8449
8450
Ref<Shader> shader;
8451
shader.instantiate();
8452
8453
String code = vshader->get_code();
8454
shader->set_code(code);
8455
8456
return shader;
8457
}
8458
8459