summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_constants.cpp3
-rw-r--r--doc/classes/@GlobalScope.xml9
-rw-r--r--doc/classes/VisualShader.xml38
-rw-r--r--doc/classes/VisualShaderNodeVarying.xml15
-rw-r--r--doc/classes/VisualShaderNodeVaryingGetter.xml9
-rw-r--r--doc/classes/VisualShaderNodeVaryingSetter.xml9
-rw-r--r--editor/animation_track_editor.cpp2
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/debugger/editor_visual_profiler.cpp2
-rw-r--r--editor/editor_node.cpp13
-rw-r--r--editor/editor_settings.cpp7
-rw-r--r--editor/editor_themes.cpp2
-rw-r--r--editor/fileserver/editor_file_server.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp4
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp1
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp22
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp8
-rw-r--r--editor/plugins/script_text_editor.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp533
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h32
-rw-r--r--editor/project_manager.cpp9
-rw-r--r--editor/scene_tree_dock.cpp2
-rw-r--r--modules/csg/csg_shape.cpp7
-rw-r--r--modules/gdscript/gdscript_editor.cpp6
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp4
-rw-r--r--modules/mono/csharp_script.cpp4
-rw-r--r--scene/gui/line_edit.cpp8
-rw-r--r--scene/register_scene_types.cpp3
-rw-r--r--scene/resources/visual_shader.cpp535
-rw-r--r--scene/resources/visual_shader.h164
33 files changed, 1379 insertions, 86 deletions
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 63e7323f7a..89926ee81b 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -168,6 +168,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_IMAGE_MASK);
BIND_CORE_ENUM_CONSTANT(INLINE_ALIGNMENT_TEXT_MASK);
+ BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, SPECIAL);
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, ESCAPE);
BIND_CORE_ENUM_CLASS_CONSTANT(Key, KEY, TAB);
@@ -422,6 +423,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, KPAD);
BIND_CORE_ENUM_CLASS_CONSTANT(KeyModifierMask, KEY_MASK, GROUP_SWITCH);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, LEFT);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, RIGHT);
BIND_CORE_ENUM_CLASS_CONSTANT(MouseButton, MOUSE_BUTTON, MIDDLE);
@@ -472,6 +474,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, SDL_MAX);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyAxis, JOY_AXIS, MAX);
+ BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NONE);
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_OFF);
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, NOTE_ON);
BIND_CORE_ENUM_CLASS_CONSTANT(MIDIMessage, MIDI_MESSAGE, AFTERTOUCH);
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 17cb50d1a4..3cfc6f3bd2 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1284,6 +1284,9 @@
<constant name="INLINE_ALIGNMENT_TEXT_MASK" value="12" enum="InlineAlignment">
A bit mask for [code]INLINE_ALIGNMENT_TO_*[/code] alignment constants.
</constant>
+ <constant name="KEY_NONE" value="0" enum="Key">
+ Enum value which doesn't correspond to any key. This is used to initialize [enum Key] properties with a generic state.
+ </constant>
<constant name="KEY_SPECIAL" value="16777216" enum="Key">
Keycodes with this bit applied are non-printable.
</constant>
@@ -2040,6 +2043,9 @@
<constant name="KEY_MASK_GROUP_SWITCH" value="1073741824" enum="KeyModifierMask">
Group Switch key mask.
</constant>
+ <constant name="MOUSE_BUTTON_NONE" value="0" enum="MouseButton">
+ Enum value which doesn't correspond to any mouse button. This is used to initialize [enum MouseButton] properties with a generic state.
+ </constant>
<constant name="MOUSE_BUTTON_LEFT" value="1" enum="MouseButton">
Left mouse button.
</constant>
@@ -2184,6 +2190,9 @@
<constant name="JOY_AXIS_MAX" value="10" enum="JoyAxis">
The maximum number of game controller axes: OpenVR supports up to 5 Joysticks making a total of 10 axes.
</constant>
+ <constant name="MIDI_MESSAGE_NONE" value="0" enum="MIDIMessage">
+ Enum value which doesn't correspond to any MIDI message. This is used to initialize [enum MIDIMessage] properties with a generic state.
+ </constant>
<constant name="MIDI_MESSAGE_NOTE_OFF" value="8" enum="MIDIMessage">
MIDI note OFF message. See the documentation of [InputEventMIDI] for information of how to use MIDI inputs.
</constant>
diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml
index 3c5a6f3a33..138aad8d47 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -20,6 +20,14 @@
Adds the specified node to the shader.
</description>
</method>
+ <method name="add_varying">
+ <return type="void" />
+ <argument index="0" name="name" type="String" />
+ <argument index="1" name="mode" type="int" enum="VisualShader.VaryingMode" />
+ <argument index="2" name="type" type="int" enum="VisualShader.VaryingType" />
+ <description>
+ </description>
+ </method>
<method name="can_connect_nodes" qualifiers="const">
<return type="bool" />
<argument index="0" name="type" type="int" enum="VisualShader.Type" />
@@ -100,6 +108,12 @@
<description>
</description>
</method>
+ <method name="has_varying" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ </description>
+ </method>
<method name="is_node_connection" qualifiers="const">
<return type="bool" />
<argument index="0" name="type" type="int" enum="VisualShader.Type" />
@@ -119,6 +133,12 @@
Removes the specified node from the shader.
</description>
</method>
+ <method name="remove_varying">
+ <return type="void" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ </description>
+ </method>
<method name="replace_node">
<return type="void" />
<argument index="0" name="type" type="int" enum="VisualShader.Type" />
@@ -182,6 +202,24 @@
<constant name="TYPE_MAX" value="10" enum="Type">
Represents the size of the [enum Type] enum.
</constant>
+ <constant name="VARYING_MODE_VERTEX_TO_FRAG_LIGHT" value="0" enum="VaryingMode">
+ </constant>
+ <constant name="VARYING_MODE_FRAG_TO_LIGHT" value="1" enum="VaryingMode">
+ </constant>
+ <constant name="VARYING_MODE_MAX" value="2" enum="VaryingMode">
+ </constant>
+ <constant name="VARYING_TYPE_FLOAT" value="0" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_VECTOR_2D" value="1" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_VECTOR_3D" value="2" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_COLOR" value="3" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_TRANSFORM" value="4" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_MAX" value="5" enum="VaryingType">
+ </constant>
<constant name="NODE_ID_INVALID" value="-1">
</constant>
<constant name="NODE_ID_OUTPUT" value="0">
diff --git a/doc/classes/VisualShaderNodeVarying.xml b/doc/classes/VisualShaderNodeVarying.xml
new file mode 100644
index 0000000000..0dbbd61f3a
--- /dev/null
+++ b/doc/classes/VisualShaderNodeVarying.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeVarying" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="varying_name" type="String" setter="set_varying_name" getter="get_varying_name" default="&quot;[None]&quot;">
+ </member>
+ <member name="varying_type" type="int" setter="set_varying_type" getter="get_varying_type" enum="VisualShader.VaryingType" default="0">
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/VisualShaderNodeVaryingGetter.xml b/doc/classes/VisualShaderNodeVaryingGetter.xml
new file mode 100644
index 0000000000..de30b18d67
--- /dev/null
+++ b/doc/classes/VisualShaderNodeVaryingGetter.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeVaryingGetter" inherits="VisualShaderNodeVarying" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+</class>
diff --git a/doc/classes/VisualShaderNodeVaryingSetter.xml b/doc/classes/VisualShaderNodeVaryingSetter.xml
new file mode 100644
index 0000000000..57ead3d82b
--- /dev/null
+++ b/doc/classes/VisualShaderNodeVaryingSetter.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeVaryingSetter" inherits="VisualShaderNodeVarying" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+</class>
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 3970fca3b5..6586fcd5ce 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -3588,7 +3588,7 @@ void AnimationTrackEditor::commit_insert_queue() {
}
}
- if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true)) && num_tracks > 0) {
+ if (bool(EDITOR_GET("editors/animation/confirm_insert_track")) && num_tracks > 0) {
// Potentially a new key, does not exist.
if (num_tracks == 1) {
// TRANSLATORS: %s will be replaced by a phrase describing the target of track.
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 4b263e5152..32e3c3679a 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -659,7 +659,7 @@ EditorProfiler::EditorProfiler() {
h_split->add_child(graph);
graph->set_h_size_flags(SIZE_EXPAND_FILL);
- int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024);
+ int metric_size = CLAMP(int(EDITOR_GET("debugger/profiler_frame_history_size")), 60, 1024);
frame_metrics.resize(metric_size);
total_metrics = 0;
last_metric = -1;
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 5df86c70fe..554a9dc6a5 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -789,7 +789,7 @@ EditorVisualProfiler::EditorVisualProfiler() {
h_split->add_child(graph);
graph->set_h_size_flags(SIZE_EXPAND_FILL);
- int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024);
+ int metric_size = CLAMP(int(EDITOR_GET("debugger/profiler_frame_history_size")), 60, 1024);
frame_metrics.resize(metric_size);
last_metric = -1;
//cursor_metric=-1;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 33864df7d3..42eaf8bd89 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6030,18 +6030,10 @@ EditorNode::EditorNode() {
// defs here, use EDITOR_GET in logic
EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false);
- EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true);
- EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50);
- EDITOR_DEF("run/output/always_clear_output_on_play", true);
- EDITOR_DEF("run/output/always_open_output_on_play", true);
- EDITOR_DEF("run/output/always_close_output_on_stop", true);
- EDITOR_DEF("run/auto_save/save_before_running", true);
EDITOR_DEF("interface/editor/save_on_focus_loss", false);
- EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true);
EDITOR_DEF("interface/editor/show_update_spinner", false);
EDITOR_DEF("interface/editor/update_continuously", false);
EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", true);
- EDITOR_DEF_RST("interface/scene_tabs/show_thumbnail_on_hover", true);
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "interface/inspector/default_float_step", PROPERTY_HINT_RANGE, "0,1,0"));
@@ -6055,7 +6047,6 @@ EditorNode::EditorNode() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_mode", PROPERTY_HINT_ENUM, "RGB,HSV,RAW", PROPERTY_USAGE_DEFAULT));
EDITOR_DEF("interface/inspector/default_color_picker_shape", (int32_t)ColorPicker::SHAPE_VHS_CIRCLE);
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "interface/inspector/default_color_picker_shape", PROPERTY_HINT_ENUM, "HSV Rectangle,HSV Rectangle Wheel,VHS Circle", PROPERTY_USAGE_DEFAULT));
- EDITOR_DEF("run/auto_save/save_before_running", true);
ED_SHORTCUT("canvas_item_editor/pan_view", TTR("Pan View"), Key::SPACE);
@@ -6263,8 +6254,8 @@ EditorNode::EditorNode() {
scene_tabs->set_select_with_rmb(true);
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
- scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
+ scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_min_width(int(EDITOR_GET("interface/scene_tabs/minimum_width")) * EDSCALE);
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
scene_tabs->connect("tab_button_pressed", callable_mp(this, &EditorNode::_scene_tab_script_edited));
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 0135b33bca..52ff7e3c19 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -554,6 +554,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/behavior/files/autosave_interval_secs", 0);
_initial_set("text_editor/behavior/files/restore_scripts_on_load", true);
_initial_set("text_editor/behavior/files/convert_indent_on_save", true);
+ _initial_set("text_editor/behavior/files/auto_reload_scripts_on_external_change", false);
// Script list
_initial_set("text_editor/script_list/show_members_overview", true);
@@ -586,6 +587,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Use a similar color to the 2D editor selection.
EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/selection_box_color", Color(1.0, 0.5, 0), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
+ _initial_set("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+ _initial_set("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1));
+ _initial_set("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
// If a line is a multiple of this, it uses the primary grid color.
// Use a power of 2 value by default as it's more common to use powers of 2 in level design.
@@ -709,6 +713,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// SSL
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "network/ssl/editor_ssl_certificates", _SYSTEM_CERTS_PATH, "*.crt,*.pem")
+ // Profiler
+ _initial_set("debugger/profiler_frame_history_size", 600);
+
/* Extra config */
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Name,Path,Last Edited")
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index a79ced39a3..01757dd332 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1172,7 +1172,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), SNAME("EditorIcons")));
- theme->set_constant("line_spacing", "CodeEdit", EDITOR_DEF("text_editor/appearance/whitespace/line_spacing", 6));
+ theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
// H/VSplitContainer
theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon(SNAME("GuiVsplitBg"), SNAME("EditorIcons")), 1, 1, 1, 1));
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 4a6aa11938..df0af69359 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -298,8 +298,8 @@ void EditorFileServer::_thread_start(void *s) {
void EditorFileServer::start() {
stop();
- port = EDITOR_DEF("filesystem/file_server/port", 6010);
- password = EDITOR_DEF("filesystem/file_server/password", "");
+ port = EDITOR_GET("filesystem/file_server/port");
+ password = EDITOR_GET("filesystem/file_server/password");
cmd = CMD_ACTIVATE;
}
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 9e9915cfa4..50f253b167 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -44,8 +44,8 @@
static inline void setup_http_request(HTTPRequest *request) {
request->set_use_threads(EDITOR_DEF("asset_library/use_threads", true));
- const String proxy_host = EDITOR_DEF("network/http_proxy/host", "");
- const int proxy_port = EDITOR_DEF("network/http_proxy/port", -1);
+ const String proxy_host = EDITOR_GET("network/http_proxy/host");
+ const int proxy_port = EDITOR_GET("network/http_proxy/port");
request->set_http_proxy(proxy_host, proxy_port);
request->set_https_proxy(proxy_host, proxy_port);
}
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 3d40755b7a..468341a593 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -317,7 +317,6 @@ void MeshLibraryEditorPlugin::make_visible(bool p_visible) {
}
MeshLibraryEditorPlugin::MeshLibraryEditorPlugin() {
- EDITOR_DEF("editors/grid_map/preview_size", 64);
mesh_library_editor = memnew(MeshLibraryEditor);
EditorNode::get_singleton()->get_main_control()->add_child(mesh_library_editor);
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 23f3087553..8aa8ba1f00 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -876,7 +876,7 @@ EditorNode3DGizmo::~EditorNode3DGizmo() {
/////
void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+ Color instantiated_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instantiated");
Vector<Ref<StandardMaterial3D>> mats;
@@ -918,7 +918,7 @@ void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color
}
void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top, const Color &p_albedo) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+ Color instantiated_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/instantiated");
Vector<Ref<StandardMaterial3D>> icons;
@@ -2251,7 +2251,7 @@ void Position3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
PhysicalBone3DGizmoPlugin::PhysicalBone3DGizmoPlugin() {
- create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1)));
+ create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
}
bool PhysicalBone3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -2384,7 +2384,7 @@ void PhysicalBone3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
/////
RayCast3DGizmoPlugin::RayCast3DGizmoPlugin() {
- const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
const float gizmo_value = gizmo_color.get_v();
const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
@@ -2438,7 +2438,7 @@ void SpringArm3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
SpringArm3DGizmoPlugin::SpringArm3DGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
}
@@ -2457,7 +2457,7 @@ int SpringArm3DGizmoPlugin::get_priority() const {
/////
VehicleWheel3DGizmoPlugin::VehicleWheel3DGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
}
@@ -2528,7 +2528,7 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
///////////
SoftDynamicBody3DGizmoPlugin::SoftDynamicBody3DGizmoPlugin() {
- Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
create_handle_material("handles");
}
@@ -3976,7 +3976,7 @@ void LightmapProbeGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
CollisionObject3DGizmoPlugin::CollisionObject3DGizmoPlugin() {
- const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
const float gizmo_value = gizmo_color.get_v();
const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
@@ -4026,7 +4026,7 @@ void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
CollisionShape3DGizmoPlugin::CollisionShape3DGizmoPlugin() {
- const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
const float gizmo_value = gizmo_color.get_v();
const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
@@ -4627,7 +4627,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
/////
CollisionPolygon3DGizmoPlugin::CollisionPolygon3DGizmoPlugin() {
- const Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/shape", Color(0.5, 0.7, 1));
+ const Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape");
create_material("shape_material", gizmo_color);
const float gizmo_value = gizmo_color.get_v();
const Color gizmo_color_disabled = Color(gizmo_value, gizmo_value, gizmo_value, 0.65);
@@ -5024,7 +5024,7 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba
////
Joint3DGizmoPlugin::Joint3DGizmoPlugin() {
- create_material("joint_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1)));
+ create_material("joint_material", EDITOR_GET("editors/3d_gizmos/gizmo_colors/joint"));
create_material("joint_body_a_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_a", Color(0.6, 0.8, 1)));
create_material("joint_body_b_material", EDITOR_DEF("editors/3d_gizmos/gizmo_colors/joint_body_b", Color(0.6, 0.9, 1)));
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 17c6457444..3927aaa438 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2286,7 +2286,7 @@ void Node3DEditorViewport::scale_freelook_speed(real_t scale) {
Point2i Node3DEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const {
Point2i relative;
- if (bool(EDITOR_DEF("editors/3d/navigation/warped_mouse_panning", false))) {
+ if (bool(EDITOR_GET("editors/3d/navigation/warped_mouse_panning"))) {
relative = Input::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect());
} else {
relative = p_ev_mouse_motion->get_relative();
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index f096b2abb1..2812c4aaaf 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1062,7 +1062,7 @@ void Polygon2DEditor::_uv_draw() {
for (int i = 0; i < uvs.size(); i++) {
int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0;
- if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/polygon_editor/show_previous_outline", true)) {
+ if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_GET("editors/polygon_editor/show_previous_outline")) {
uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, Math::round(EDSCALE));
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 43467a6c41..d506a1f3ab 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1046,7 +1046,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) {
bool need_ask = false;
bool need_reload = false;
- bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false));
+ bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change"));
for (int i = 0; i < tab_container->get_tab_count(); i++) {
ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_tab_control(i));
@@ -2723,7 +2723,7 @@ void ScriptEditor::_editor_settings_changed() {
_update_script_colors();
_update_script_names();
- ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true));
+ ScriptServer::set_reload_scripts_on_save(EDITOR_GET("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save"));
}
void ScriptEditor::_filesystem_changed() {
@@ -3125,7 +3125,7 @@ void ScriptEditor::_make_script_list_context_menu() {
}
void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
- if (!bool(EDITOR_DEF("text_editor/behavior/files/restore_scripts_on_load", true))) {
+ if (!bool(EDITOR_GET("text_editor/behavior/files/restore_scripts_on_load"))) {
return;
}
@@ -4039,7 +4039,7 @@ ScriptEditorPlugin::ScriptEditorPlugin() {
script_editor->hide();
- EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", true);
+ EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change");
ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true));
EDITOR_DEF("text_editor/behavior/files/open_dominant_script_on_scene_change", true);
EDITOR_DEF("text_editor/external/use_external_editor", false);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index b87f2995ed..3138801cdb 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -521,7 +521,7 @@ void ScriptTextEditor::_update_errors() {
errors_panel->pop(); // Table
CodeEdit *te = code_editor->get_text_editor();
- bool highlight_safe = EDITOR_DEF("text_editor/appearance/gutters/highlight_type_safe_lines", true);
+ bool highlight_safe = EDITOR_GET("text_editor/appearance/gutters/highlight_type_safe_lines");
bool last_is_safe = false;
for (int i = 0; i < te->get_line_count(); i++) {
if (errors.is_empty()) {
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index cea1a0e808..382138a995 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -520,7 +520,7 @@ void ShaderEditor::_check_for_external_edit() {
return;
}
- bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false));
+ bool use_autoreload = bool(EDITOR_GET("text_editor/behavior/files/auto_reload_scripts_on_external_change"));
if (shader->get_last_modified_time() != FileAccess::get_modified_time(shader->get_path())) {
if (use_autoreload) {
_reload_shader_from_disk();
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index a821faf6b3..94906acb63 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -555,7 +555,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
if (custom_editor) {
- 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) == ""))) {
+ 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) == ""))) {
//will be embedded in first port
} else {
port_offset++;
@@ -1074,6 +1074,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) {
hide();
} else {
if (changed) { // to avoid tree collapse
+ _update_varying_tree();
_update_options_menu();
_update_preview();
_update_graph();
@@ -1460,6 +1461,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
edit_type_fog->set_visible(false);
edit_type = edit_type_sky;
custom_mode_box->set_visible(false);
+ varying_button->hide();
mode = MODE_FLAGS_SKY;
} else if (p_which == VisualShader::MODE_FOG) {
edit_type_standard->set_visible(false);
@@ -1468,6 +1470,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
edit_type_fog->set_visible(true);
edit_type = edit_type_fog;
custom_mode_box->set_visible(false);
+ varying_button->hide();
mode = MODE_FLAGS_FOG;
} else if (p_which == VisualShader::MODE_PARTICLES) {
edit_type_standard->set_visible(false);
@@ -1480,6 +1483,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
} else {
custom_mode_box->set_visible(true);
}
+ varying_button->hide();
mode = MODE_FLAGS_PARTICLES;
} else {
edit_type_particles->set_visible(false);
@@ -1488,6 +1492,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
edit_type_fog->set_visible(false);
edit_type = edit_type_standard;
custom_mode_box->set_visible(false);
+ varying_button->show();
mode = MODE_FLAGS_SPATIAL_CANVASITEM;
}
visual_shader->set_shader_type(get_current_shader_type());
@@ -1616,6 +1621,7 @@ void VisualShaderEditor::_update_graph() {
Vector<int> nodes = visual_shader->get_node_list(type);
_update_uniforms(false);
+ _update_varyings();
graph_plugin->clear_links();
graph_plugin->make_dirty(true);
@@ -2778,6 +2784,116 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri
}
}
+void VisualShaderEditor::_add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) {
+ undo_redo->create_action(vformat(TTR("Add Varying to Visual Shader: %s"), p_name));
+
+ undo_redo->add_do_method(visual_shader.ptr(), "add_varying", p_name, p_mode, p_type);
+ undo_redo->add_undo_method(visual_shader.ptr(), "remove_varying", p_name);
+
+ undo_redo->add_do_method(this, "_update_varyings");
+ undo_redo->add_undo_method(this, "_update_varyings");
+
+ for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
+ if (p_mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
+ continue;
+ }
+
+ VisualShader::Type type = VisualShader::Type(i);
+ Vector<int> nodes = visual_shader->get_node_list(type);
+
+ for (int j = 0; j < nodes.size(); j++) {
+ int node_id = nodes[j];
+ Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
+ Ref<VisualShaderNodeVarying> var = vsnode;
+
+ if (var.is_valid()) {
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
+ }
+ }
+ }
+
+ undo_redo->add_do_method(this, "_update_varying_tree");
+ undo_redo->add_undo_method(this, "_update_varying_tree");
+ undo_redo->commit_action();
+}
+
+void VisualShaderEditor::_remove_varying(const String &p_name) {
+ undo_redo->create_action(vformat(TTR("Remove Varying from Visual Shader: %s"), p_name));
+
+ VisualShader::VaryingMode mode = visual_shader->get_varying_mode(p_name);
+
+ undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", p_name);
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", p_name, mode, visual_shader->get_varying_type(p_name));
+
+ undo_redo->add_do_method(this, "_update_varyings");
+ undo_redo->add_undo_method(this, "_update_varyings");
+
+ for (int i = 0; i <= VisualShader::TYPE_LIGHT; i++) {
+ if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT && i == 0) {
+ continue;
+ }
+
+ VisualShader::Type type = VisualShader::Type(i);
+ Vector<int> nodes = visual_shader->get_node_list(type);
+
+ for (int j = 0; j < nodes.size(); j++) {
+ int node_id = nodes[j];
+ Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, node_id);
+ Ref<VisualShaderNodeVarying> var = vsnode;
+
+ if (var.is_valid()) {
+ String var_name = var->get_varying_name();
+
+ if (var_name == p_name) {
+ undo_redo->add_do_method(var.ptr(), "set_varying_name", "[None]");
+ undo_redo->add_undo_method(var.ptr(), "set_varying_name", var_name);
+ undo_redo->add_do_method(var.ptr(), "set_varying_type", VisualShader::VARYING_TYPE_FLOAT);
+ undo_redo->add_undo_method(var.ptr(), "set_varying_type", var->get_varying_type());
+ }
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type, node_id);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type, node_id);
+ }
+ }
+
+ List<VisualShader::Connection> connections;
+ visual_shader->get_node_connections(type, &connections);
+
+ for (VisualShader::Connection &E : connections) {
+ Ref<VisualShaderNodeVaryingGetter> var_getter = Object::cast_to<VisualShaderNodeVaryingGetter>(visual_shader->get_node(type, E.from_node).ptr());
+ if (var_getter.is_valid() && E.from_port > 0) {
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ }
+ Ref<VisualShaderNodeVaryingSetter> var_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(visual_shader->get_node(type, E.to_node).ptr());
+ if (var_setter.is_valid() && E.to_port > 0) {
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ }
+ }
+ }
+
+ undo_redo->add_do_method(this, "_update_varying_tree");
+ undo_redo->add_undo_method(this, "_update_varying_tree");
+ undo_redo->commit_action();
+}
+
+void VisualShaderEditor::_update_varyings() {
+ VisualShaderNodeVarying::clear_varyings();
+
+ for (int i = 0; i < visual_shader->get_varyings_count(); i++) {
+ const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
+
+ if (var != nullptr) {
+ VisualShaderNodeVarying::add_varying(var->name, var->mode, var->type);
+ }
+ }
+}
+
void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) {
VisualShader::Type type = get_current_shader_type();
drag_buffer.push_back({ type, p_node, p_from, p_to });
@@ -3364,6 +3480,49 @@ void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNod
node_filter->select_all();
}
+void VisualShaderEditor::_show_varying_menu() {
+ varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), visual_shader->get_varyings_count() == 0);
+ varying_options->set_position(graph->get_screen_position() + varying_button->get_position() + Size2(0, varying_button->get_size().height));
+ varying_options->popup();
+}
+
+void VisualShaderEditor::_varying_menu_id_pressed(int p_idx) {
+ switch (VaryingMenuOptions(p_idx)) {
+ case VaryingMenuOptions::ADD: {
+ _show_add_varying_dialog();
+ } break;
+ case VaryingMenuOptions::REMOVE: {
+ _show_remove_varying_dialog();
+ } break;
+ default:
+ break;
+ }
+}
+
+void VisualShaderEditor::_show_add_varying_dialog() {
+ _varying_name_changed(varying_name->get_text());
+
+ add_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
+ add_varying_dialog->popup();
+
+ // Keep dialog within window bounds.
+ Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
+ Rect2 dialog_rect = Rect2(add_varying_dialog->get_position(), add_varying_dialog->get_size());
+ Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).max(Vector2());
+ add_varying_dialog->set_position(add_varying_dialog->get_position() - difference);
+}
+
+void VisualShaderEditor::_show_remove_varying_dialog() {
+ remove_varying_dialog->set_position(graph->get_screen_position() + varying_button->get_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
+ remove_varying_dialog->popup();
+
+ // Keep dialog within window bounds.
+ Rect2 window_rect = Rect2(DisplayServer::get_singleton()->window_get_position(), DisplayServer::get_singleton()->window_get_size());
+ Rect2 dialog_rect = Rect2(remove_varying_dialog->get_position(), remove_varying_dialog->get_size());
+ Vector2 difference = (dialog_rect.get_end() - window_rect.get_end()).max(Vector2());
+ remove_varying_dialog->set_position(remove_varying_dialog->get_position() - difference);
+}
+
void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
Ref<InputEventKey> ie = p_ie;
if (ie.is_valid() && (ie->get_keycode() == Key::UP || ie->get_keycode() == Key::DOWN || ie->get_keycode() == Key::ENTER || ie->get_keycode() == Key::KP_ENTER)) {
@@ -3416,8 +3575,10 @@ void VisualShaderEditor::_notification(int p_what) {
Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color");
Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color");
Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color");
+ Color error_color = get_theme_color(SNAME("error_color"), SNAME("Editor"));
preview_text->add_theme_color_override("background_color", background_color);
+ varying_error_label->add_theme_color_override("font_color", error_color);
for (const String &E : keyword_list) {
if (ShaderLanguage::is_control_flow_keyword(E)) {
@@ -3445,7 +3606,7 @@ void VisualShaderEditor::_notification(int p_what) {
error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Panel")));
error_label->add_theme_font_override("font", get_theme_font(SNAME("status_source"), SNAME("EditorFonts")));
error_label->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("status_source_size"), SNAME("EditorFonts")));
- error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ error_label->add_theme_color_override("font_color", error_color);
}
tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
@@ -3828,6 +3989,75 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_
undo_redo->commit_action();
}
+void VisualShaderEditor::_varying_select_item(Ref<VisualShaderNodeVarying> p_varying, String p_name) {
+ String prev_name = p_varying->get_varying_name();
+
+ if (p_name == prev_name) {
+ return;
+ }
+
+ bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action(TTR("Varying Name Changed"));
+
+ undo_redo->add_do_method(p_varying.ptr(), "set_varying_name", p_name);
+ undo_redo->add_undo_method(p_varying.ptr(), "set_varying_name", prev_name);
+
+ VisualShader::VaryingType vtype = p_varying->get_varying_type_by_name(p_name);
+ VisualShader::VaryingType prev_vtype = p_varying->get_varying_type_by_name(prev_name);
+
+ bool type_changed = vtype != prev_vtype;
+
+ if (type_changed) {
+ undo_redo->add_do_method(p_varying.ptr(), "set_varying_type", vtype);
+ undo_redo->add_undo_method(p_varying.ptr(), "set_varying_type", prev_vtype);
+ }
+
+ // update ports
+ for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
+ VisualShader::Type type = VisualShader::Type(type_id);
+ int id = visual_shader->find_node_id(type, p_varying);
+
+ if (id != VisualShader::NODE_ID_INVALID) {
+ if (type_changed) {
+ List<VisualShader::Connection> conns;
+ visual_shader->get_node_connections(type, &conns);
+
+ for (const VisualShader::Connection &E : conns) {
+ if (is_getter) {
+ if (E.from_node == id) {
+ 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))) {
+ continue;
+ }
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ }
+ } else {
+ if (E.to_node == id) {
+ 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))) {
+ continue;
+ }
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ }
+ }
+ }
+ }
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
+ break;
+ }
+ }
+
+ undo_redo->commit_action();
+}
+
void VisualShaderEditor::_float_constant_selected(int p_which) {
ERR_FAIL_INDEX(p_which, MAX_FLOAT_CONST_DEFS);
@@ -3882,6 +4112,92 @@ void VisualShaderEditor::_member_cancel() {
from_slot = -1;
}
+void VisualShaderEditor::_update_varying_tree() {
+ varyings->clear();
+ TreeItem *root = varyings->create_item();
+
+ int count = visual_shader->get_varyings_count();
+
+ for (int i = 0; i < count; i++) {
+ const VisualShader::Varying *varying = visual_shader->get_varying_by_index(i);
+
+ if (varying) {
+ TreeItem *item = varyings->create_item(root);
+ item->set_text(0, varying->name);
+
+ if (i == 0) {
+ item->select(0);
+ }
+
+ switch (varying->type) {
+ case VisualShader::VARYING_TYPE_FLOAT:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")));
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")));
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")));
+ break;
+ case VisualShader::VARYING_TYPE_COLOR:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
+ break;
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ varying_options->set_item_disabled(int(VaryingMenuOptions::REMOVE), count == 0);
+}
+
+void VisualShaderEditor::_varying_create() {
+ _add_varying(varying_name->get_text(), (VisualShader::VaryingMode)varying_mode->get_selected(), (VisualShader::VaryingType)varying_type->get_selected());
+ add_varying_dialog->hide();
+}
+
+void VisualShaderEditor::_varying_name_changed(const String &p_text) {
+ String name = p_text;
+
+ if (!name.is_valid_identifier()) {
+ varying_error_label->show();
+ varying_error_label->set_text(TTR("Invalid name for varying."));
+ add_varying_dialog->get_ok_button()->set_disabled(true);
+ return;
+ }
+ if (visual_shader->has_varying(name)) {
+ varying_error_label->show();
+ varying_error_label->set_text(TTR("Varying with that name is already exist."));
+ add_varying_dialog->get_ok_button()->set_disabled(true);
+ return;
+ }
+ if (varying_error_label->is_visible()) {
+ varying_error_label->hide();
+ add_varying_dialog->set_size(Size2(add_varying_dialog->get_size().x, 0));
+ }
+ add_varying_dialog->get_ok_button()->set_disabled(false);
+}
+
+void VisualShaderEditor::_varying_deleted() {
+ TreeItem *item = varyings->get_selected();
+
+ if (item != nullptr) {
+ _remove_varying(item->get_text(0));
+ remove_varying_dialog->hide();
+ }
+}
+
+void VisualShaderEditor::_varying_selected() {
+ add_varying_dialog->get_ok_button()->set_disabled(false);
+}
+
+void VisualShaderEditor::_varying_unselected() {
+ add_varying_dialog->get_ok_button()->set_disabled(true);
+}
+
void VisualShaderEditor::_tools_menu_option(int p_idx) {
TreeItem *category = members->get_root()->get_first_child();
@@ -4155,9 +4471,12 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_node_changed", &VisualShaderEditor::_node_changed);
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
ClassDB::bind_method("_uniform_select_item", &VisualShaderEditor::_uniform_select_item);
+ ClassDB::bind_method("_varying_select_item", &VisualShaderEditor::_varying_select_item);
ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size);
ClassDB::bind_method("_clear_copy_buffer", &VisualShaderEditor::_clear_copy_buffer);
ClassDB::bind_method("_update_uniforms", &VisualShaderEditor::_update_uniforms);
+ ClassDB::bind_method("_update_varyings", &VisualShaderEditor::_update_varyings);
+ ClassDB::bind_method("_update_varying_tree", &VisualShaderEditor::_update_varying_tree);
ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode);
ClassDB::bind_method("_nodes_dragged", &VisualShaderEditor::_nodes_dragged);
ClassDB::bind_method("_float_constant_selected", &VisualShaderEditor::_float_constant_selected);
@@ -4284,11 +4603,23 @@ VisualShaderEditor::VisualShaderEditor() {
add_node = memnew(Button);
add_node->set_flat(true);
- graph->get_zoom_hbox()->add_child(add_node);
add_node->set_text(TTR("Add Node..."));
+ graph->get_zoom_hbox()->add_child(add_node);
graph->get_zoom_hbox()->move_child(add_node, 0);
add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false, VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PORT_TYPE_MAX));
+ varying_button = memnew(Button);
+ varying_button->set_flat(true);
+ varying_button->set_text(TTR("Manage Varyings"));
+ graph->get_zoom_hbox()->add_child(varying_button);
+ varying_button->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_varying_menu));
+
+ varying_options = memnew(PopupMenu);
+ add_child(varying_options);
+ varying_options->add_item(TTR("Add Varying"), int(VaryingMenuOptions::ADD));
+ varying_options->add_item(TTR("Remove Varying"), int(VaryingMenuOptions::REMOVE));
+ varying_options->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_varying_menu_id_pressed));
+
preview_shader = memnew(Button);
preview_shader->set_flat(true);
preview_shader->set_toggle_mode(true);
@@ -4412,6 +4743,74 @@ VisualShaderEditor::VisualShaderEditor() {
members_dialog->connect("cancelled", callable_mp(this, &VisualShaderEditor::_member_cancel));
add_child(members_dialog);
+ // add varyings dialog
+ {
+ add_varying_dialog = memnew(ConfirmationDialog);
+ add_varying_dialog->set_title(TTR("Create Shader Varying"));
+ add_varying_dialog->set_exclusive(false);
+ add_varying_dialog->get_ok_button()->set_text(TTR("Create"));
+ add_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_create));
+ add_varying_dialog->get_ok_button()->set_disabled(true);
+ add_child(add_varying_dialog);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ add_varying_dialog->add_child(vb);
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+ vb->add_child(hb);
+ hb->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ varying_type = memnew(OptionButton);
+ hb->add_child(varying_type);
+ varying_type->add_item("Float");
+ varying_type->add_item("Vector2");
+ varying_type->add_item("Vector3");
+ varying_type->add_item("Color");
+ varying_type->add_item("Transform");
+
+ varying_name = memnew(LineEdit);
+ hb->add_child(varying_name);
+ varying_name->set_custom_minimum_size(Size2(150 * EDSCALE, 0));
+ varying_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ varying_name->connect("text_changed", callable_mp(this, &VisualShaderEditor::_varying_name_changed));
+
+ varying_mode = memnew(OptionButton);
+ hb->add_child(varying_mode);
+ varying_mode->add_item("Vertex -> [Fragment, Light]");
+ varying_mode->add_item("Fragment -> Light");
+
+ varying_error_label = memnew(Label);
+ vb->add_child(varying_error_label);
+ varying_error_label->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ varying_error_label->hide();
+ }
+
+ // remove varying dialog
+ {
+ remove_varying_dialog = memnew(ConfirmationDialog);
+ remove_varying_dialog->set_title(TTR("Delete Shader Varying"));
+ remove_varying_dialog->set_exclusive(false);
+ remove_varying_dialog->get_ok_button()->set_text(TTR("Delete"));
+ remove_varying_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualShaderEditor::_varying_deleted));
+ add_child(remove_varying_dialog);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ remove_varying_dialog->add_child(vb);
+
+ varyings = memnew(Tree);
+ vb->add_child(varyings);
+ varyings->set_h_size_flags(SIZE_EXPAND_FILL);
+ varyings->set_v_size_flags(SIZE_EXPAND_FILL);
+ varyings->set_hide_root(true);
+ varyings->set_allow_reselect(true);
+ varyings->set_hide_folding(false);
+ varyings->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
+ varyings->connect("item_activated", callable_mp(this, &VisualShaderEditor::_varying_deleted));
+ varyings->connect("item_selected", callable_mp(this, &VisualShaderEditor::_varying_selected));
+ varyings->connect("nothing_selected", callable_mp(this, &VisualShaderEditor::_varying_unselected));
+ }
+
alert = memnew(AcceptDialog);
alert->get_label()->set_autowrap_mode(Label::AUTOWRAP_WORD);
alert->get_label()->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
@@ -4578,6 +4977,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
@@ -4591,6 +4994,9 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewIndex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_index"), { "view_index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo"), { "albedo" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
@@ -4601,6 +5007,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Metallic", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness"), { "roughness" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("ShadowAttenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_attenuation"), { "shadow_attenuation" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular"), { "specular" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), { "view" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
@@ -4610,9 +5017,11 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Canvas", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas"), { "canvas" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Screen", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "screen"), { "screen" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), { "world" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("AtLightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
@@ -4989,6 +5398,10 @@ VisualShaderEditor::VisualShaderEditor() {
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.")));
add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants.")));
add_options.push_back(AddOption("UniformRef", "Special", "", "VisualShaderNodeUniformRef", TTR("A reference to an existing uniform.")));
+ add_options.push_back(AddOption("VaryingGetter", "Special", "", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("VaryingSetter", "Special", "", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("VaryingGetter", "Special", "", "VisualShaderNodeVaryingGetter", TTR("Get varying parameter."), {}, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("VaryingSetter", "Special", "", "VisualShaderNodeVaryingSetter", TTR("Set varying parameter."), {}, -1, TYPE_FLAGS_VERTEX | TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
custom_node_option_idx = add_options.size();
@@ -5102,6 +5515,82 @@ public:
////////////////
+class VisualShaderNodePluginVaryingEditor : public OptionButton {
+ GDCLASS(VisualShaderNodePluginVaryingEditor, OptionButton);
+
+ Ref<VisualShaderNodeVarying> varying;
+
+public:
+ void _notification(int p_what) {
+ if (p_what == NOTIFICATION_READY) {
+ connect("item_selected", callable_mp(this, &VisualShaderNodePluginVaryingEditor::_item_selected));
+ }
+ }
+
+ void _item_selected(int p_item) {
+ VisualShaderEditor *editor = VisualShaderEditor::get_singleton();
+ if (editor) {
+ editor->call_deferred(SNAME("_varying_select_item"), varying, get_item_text(p_item));
+ }
+ }
+
+ void setup(const Ref<VisualShaderNodeVarying> &p_varying, VisualShader::Type p_type) {
+ varying = p_varying;
+
+ Ref<Texture2D> type_icon[] = {
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
+ };
+
+ bool is_getter = Ref<VisualShaderNodeVaryingGetter>(p_varying.ptr()).is_valid();
+
+ add_item("[None]");
+
+ int to_select = -1;
+ for (int i = 0, j = 0; i < varying->get_varyings_count(); i++) {
+ VisualShader::VaryingMode mode = varying->get_varying_mode_by_index(i);
+ if (is_getter) {
+ if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
+ if (p_type != VisualShader::TYPE_LIGHT) {
+ j++;
+ continue;
+ }
+ } else {
+ if (p_type != VisualShader::TYPE_FRAGMENT && p_type != VisualShader::TYPE_LIGHT) {
+ j++;
+ continue;
+ }
+ }
+ } else {
+ if (mode == VisualShader::VARYING_MODE_FRAG_TO_LIGHT) {
+ if (p_type != VisualShader::TYPE_FRAGMENT) {
+ j++;
+ continue;
+ }
+ } else {
+ if (p_type != VisualShader::TYPE_VERTEX) {
+ j++;
+ continue;
+ }
+ }
+ }
+ if (varying->get_varying_name() == varying->get_varying_name_by_index(i)) {
+ to_select = i - j + 1;
+ }
+ add_icon_item(type_icon[varying->get_varying_type_by_index(i)], varying->get_varying_name_by_index(i));
+ }
+
+ if (to_select >= 0) {
+ select(to_select);
+ }
+ }
+};
+
+////////////////
+
class VisualShaderNodePluginUniformRefEditor : public OptionButton {
GDCLASS(VisualShaderNodePluginUniformRefEditor, OptionButton);
@@ -5280,18 +5769,24 @@ public:
};
Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) {
+ Ref<VisualShader> p_shader = Ref<VisualShader>(p_parent_resource.ptr());
+
+ if (p_shader.is_valid() && (p_node->is_class("VisualShaderNodeVaryingGetter") || p_node->is_class("VisualShaderNodeVaryingSetter"))) {
+ VisualShaderNodePluginVaryingEditor *editor = memnew(VisualShaderNodePluginVaryingEditor);
+ editor->setup(p_node, p_shader->get_shader_type());
+ return editor;
+ }
+
if (p_node->is_class("VisualShaderNodeUniformRef")) {
- //create input
- VisualShaderNodePluginUniformRefEditor *uniform_editor = memnew(VisualShaderNodePluginUniformRefEditor);
- uniform_editor->setup(p_node);
- return uniform_editor;
+ VisualShaderNodePluginUniformRefEditor *editor = memnew(VisualShaderNodePluginUniformRefEditor);
+ editor->setup(p_node);
+ return editor;
}
if (p_node->is_class("VisualShaderNodeInput")) {
- //create input
- VisualShaderNodePluginInputEditor *input_editor = memnew(VisualShaderNodePluginInputEditor);
- input_editor->setup(p_node);
- return input_editor;
+ VisualShaderNodePluginInputEditor *editor = memnew(VisualShaderNodePluginInputEditor);
+ editor->setup(p_node);
+ return editor;
}
Vector<StringName> properties = p_node->get_editable_properties();
@@ -5408,6 +5903,22 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
}
}
+ //4. delete varyings (if needed)
+ if (p_which == VisualShader::MODE_PARTICLES || p_which == VisualShader::MODE_SKY || p_which == VisualShader::MODE_FOG) {
+ int var_count = visual_shader->get_varyings_count();
+
+ if (var_count > 0) {
+ for (int i = 0; i < var_count; i++) {
+ const VisualShader::Varying *var = visual_shader->get_varying_by_index(i);
+ undo_redo->add_do_method(visual_shader.ptr(), "remove_varying", var->name);
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_varying", var->name, var->mode, var->type);
+ }
+
+ undo_redo->add_do_method(editor, "_update_varyings");
+ undo_redo->add_undo_method(editor, "_update_varyings");
+ }
+ }
+
undo_redo->add_do_method(editor, "_update_options_menu");
undo_redo->add_undo_method(editor, "_update_options_menu");
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 02beba971b..e26b606397 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -139,6 +139,8 @@ class VisualShaderEditor : public VBoxContainer {
Ref<VisualShader> visual_shader;
GraphEdit *graph = nullptr;
Button *add_node = nullptr;
+ Button *varying_button = nullptr;
+ PopupMenu *varying_options = nullptr;
Button *preview_shader = nullptr;
OptionButton *edit_type = nullptr;
@@ -169,6 +171,15 @@ class VisualShaderEditor : public VBoxContainer {
PopupMenu *constants_submenu = nullptr;
MenuButton *tools = nullptr;
+ ConfirmationDialog *add_varying_dialog = nullptr;
+ OptionButton *varying_type = nullptr;
+ LineEdit *varying_name = nullptr;
+ OptionButton *varying_mode = nullptr;
+ Label *varying_error_label = nullptr;
+
+ ConfirmationDialog *remove_varying_dialog = nullptr;
+ Tree *varyings = nullptr;
+
PopupPanel *comment_title_change_popup = nullptr;
LineEdit *comment_title_change_edit = nullptr;
@@ -232,6 +243,11 @@ class VisualShaderEditor : public VBoxContainer {
SET_COMMENT_DESCRIPTION,
};
+ enum class VaryingMenuOptions {
+ ADD,
+ REMOVE,
+ };
+
Tree *members = nullptr;
AcceptDialog *alert = nullptr;
LineEdit *node_filter = nullptr;
@@ -241,6 +257,11 @@ class VisualShaderEditor : public VBoxContainer {
void _tools_menu_option(int p_idx);
void _show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type = VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PortType p_output_port_type = VisualShaderNode::PORT_TYPE_MAX);
+ void _show_varying_menu();
+ void _varying_menu_id_pressed(int p_idx);
+ void _show_add_varying_dialog();
+ void _show_remove_varying_dialog();
+
void _update_graph();
struct AddOption {
@@ -291,6 +312,8 @@ class VisualShaderEditor : public VBoxContainer {
void _setup_node(VisualShaderNode *p_node, const Vector<Variant> &p_ops);
void _add_node(int p_idx, const Vector<Variant> &p_ops, String p_resource_path = "", int p_node_idx = -1);
+ void _add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type);
+ void _remove_varying(const String &p_name);
void _update_options_menu();
void _set_mode(int p_which);
@@ -394,6 +417,7 @@ class VisualShaderEditor : public VBoxContainer {
void _input_select_item(Ref<VisualShaderNodeInput> input, String name);
void _uniform_select_item(Ref<VisualShaderNodeUniformRef> p_uniform, String p_name);
+ void _varying_select_item(Ref<VisualShaderNodeVarying> p_varying, String p_name);
void _float_constant_selected(int p_which);
@@ -425,6 +449,13 @@ class VisualShaderEditor : public VBoxContainer {
void _member_create();
void _member_cancel();
+ void _varying_create();
+ void _varying_name_changed(const String &p_text);
+ void _varying_deleted();
+ void _varying_selected();
+ void _varying_unselected();
+ void _update_varying_tree();
+
Vector2 menu_point;
void _node_menu_id_pressed(int p_idx);
@@ -436,6 +467,7 @@ class VisualShaderEditor : public VBoxContainer {
void _update_created_node(GraphNode *node);
void _update_uniforms(bool p_update_refs);
void _update_uniform_refs(Set<String> &p_names);
+ void _update_varyings();
void _visibility_changed();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 79aed36eeb..78f6fe58d0 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1057,6 +1057,8 @@ public:
}
};
+ bool project_opening_initiated;
+
ProjectList();
~ProjectList();
@@ -1136,6 +1138,7 @@ ProjectList::ProjectList() {
add_child(_scroll_children);
_icon_load_index = 0;
+ project_opening_initiated = false;
}
ProjectList::~ProjectList() {
@@ -1818,7 +1821,9 @@ void ProjectList::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) {
emit_signal(SNAME(SIGNAL_SELECTION_CHANGED));
- if (!mb->is_ctrl_pressed() && mb->is_double_click()) {
+ // Do not allow opening a project more than once using a single project manager instance.
+ // Opening the same project in several editor instances at once can lead to various issues.
+ if (!mb->is_ctrl_pressed() && mb->is_double_click() && !project_opening_initiated) {
emit_signal(SNAME(SIGNAL_PROJECT_ASK_OPEN));
}
}
@@ -2140,6 +2145,8 @@ void ProjectManager::_open_selected_projects() {
ERR_FAIL_COND(err);
}
+ _project_list->project_opening_initiated = true;
+
_dim_window();
get_tree()->quit();
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 628e7880a1..571b87a0aa 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1535,7 +1535,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_
}
}
- bool autorename_animation_tracks = bool(EDITOR_DEF("editors/animation/autorename_animation_tracks", true));
+ bool autorename_animation_tracks = bool(EDITOR_GET("editors/animation/autorename_animation_tracks"));
if (autorename_animation_tracks && Object::cast_to<AnimationPlayer>(p_base)) {
AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_base);
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 39e4751be3..3bb2bc3a4d 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -955,6 +955,10 @@ CSGBrush *CSGSphere3D::_build_brush() {
double u0 = double(j) / radial_segments;
double longitude1 = longitude_step * (j + 1);
+ if (j == radial_segments - 1) {
+ longitude1 = 0;
+ }
+
double x1 = Math::sin(longitude1);
double z1 = Math::cos(longitude1);
double u1 = double(j + 1) / radial_segments;
@@ -1271,6 +1275,9 @@ CSGBrush *CSGCylinder3D::_build_brush() {
for (int i = 0; i < sides; i++) {
float inc = float(i) / sides;
float inc_n = float((i + 1)) / sides;
+ if (i == sides - 1) {
+ inc_n = 0;
+ }
float ang = inc * Math_TAU;
float ang_n = inc_n * Math_TAU;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 6fb95d32ca..350962ba1b 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -65,7 +65,7 @@ Ref<Script> GDScriptLanguage::make_template(const String &p_template, const Stri
script.instantiate();
String processed_template = p_template;
#ifdef TOOLS_ENABLED
- if (!EDITOR_DEF("text_editor/completion/add_type_hints", false)) {
+ if (!EDITOR_GET("text_editor/completion/add_type_hints")) {
processed_template = processed_template.replace(": int", "")
.replace(": String", "")
.replace(": float", "")
@@ -2771,10 +2771,10 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
String GDScriptLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", false);
+ bool use_space_indentation = EDITOR_GET("text_editor/behavior/indent/type");
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
+ int indent_size = EDITOR_GET("text_editor/behavior/indent/size");
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index a05905cbc3..e8e096d52b 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -823,7 +823,7 @@ void GridMapEditor::_icon_size_changed(float p_value) {
void GridMapEditor::update_palette() {
int selected = mesh_library_palette->get_current();
- float min_size = EDITOR_DEF("editors/grid_map/preview_size", 64);
+ float min_size = EDITOR_GET("editors/grid_map/preview_size");
min_size *= EDSCALE;
mesh_library_palette->clear();
@@ -1207,7 +1207,7 @@ GridMapEditor::GridMapEditor() {
settings_pick_distance->set_max(10000.0f);
settings_pick_distance->set_min(500.0f);
settings_pick_distance->set_step(1.0f);
- settings_pick_distance->set_value(EDITOR_DEF("editors/grid_map/pick_distance", 5000.0));
+ settings_pick_distance->set_value(EDITOR_GET("editors/grid_map/pick_distance"));
settings_vbc->add_margin_child(TTR("Pick Distance:"), settings_pick_distance);
options->get_popup()->connect("id_pressed", callable_mp(this, &GridMapEditor::_menu_option));
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 085ab9a467..c0b0d63600 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -527,10 +527,10 @@ String CSharpLanguage::make_function(const String &, const String &, const Packe
String CSharpLanguage::_get_indentation() const {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- bool use_space_indentation = EDITOR_DEF("text_editor/behavior/indent/type", 0);
+ bool use_space_indentation = EDITOR_GET("text_editor/behavior/indent/type");
if (use_space_indentation) {
- int indent_size = EDITOR_DEF("text_editor/behavior/indent/size", 4);
+ int indent_size = EDITOR_GET("text_editor/behavior/indent/size");
String space_indent = "";
for (int i = 0; i < indent_size; i++) {
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 6ad296d7c7..da39a3d387 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -647,8 +647,8 @@ void LineEdit::_notification(int p_what) {
#ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE: {
if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
- set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
+ set_caret_blink_speed(EDITOR_GET("text_editor/appearance/caret/caret_blink_speed"));
if (!EditorSettings::get_singleton()->is_connected("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed))) {
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed));
@@ -1944,8 +1944,8 @@ PopupMenu *LineEdit::get_menu() const {
void LineEdit::_editor_settings_changed() {
#ifdef TOOLS_ENABLED
- set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
+ set_caret_blink_speed(EDITOR_GET("text_editor/appearance/caret/caret_blink_speed"));
#endif
}
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 228733c4c2..0b66ff004b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -634,6 +634,9 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeCompare);
GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd);
GDREGISTER_CLASS(VisualShaderNodeBillboard);
+ GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVarying);
+ GDREGISTER_CLASS(VisualShaderNodeVaryingSetter);
+ GDREGISTER_CLASS(VisualShaderNodeVaryingGetter);
GDREGISTER_CLASS(VisualShaderNodeSDFToScreenUV);
GDREGISTER_CLASS(VisualShaderNodeScreenUVToSDF);
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 47ca643029..03b768e869 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -555,6 +555,72 @@ VisualShader::Type VisualShader::get_shader_type() const {
return current_type;
}
+void VisualShader::add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type) {
+ ERR_FAIL_COND(!p_name.is_valid_identifier());
+ ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
+ ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
+ ERR_FAIL_COND(varyings.has(p_name));
+ Varying var = Varying(p_name, p_mode, p_type);
+ varyings[p_name] = var;
+ varyings_list.push_back(var);
+ _queue_update();
+}
+
+void VisualShader::remove_varying(const String &p_name) {
+ ERR_FAIL_COND(!varyings.has(p_name));
+ varyings.erase(p_name);
+ for (List<Varying>::Element *E = varyings_list.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ varyings_list.erase(E);
+ break;
+ }
+ }
+ _queue_update();
+}
+
+bool VisualShader::has_varying(const String &p_name) const {
+ return varyings.has(p_name);
+}
+
+int VisualShader::get_varyings_count() const {
+ return varyings_list.size();
+}
+
+const VisualShader::Varying *VisualShader::get_varying_by_index(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, varyings_list.size(), nullptr);
+ return &varyings_list[p_idx];
+}
+
+void VisualShader::set_varying_mode(const String &p_name, VaryingMode p_mode) {
+ ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
+ ERR_FAIL_COND(!varyings.has(p_name));
+ if (varyings[p_name].mode == p_mode) {
+ return;
+ }
+ varyings[p_name].mode = p_mode;
+ _queue_update();
+}
+
+VisualShader::VaryingMode VisualShader::get_varying_mode(const String &p_name) {
+ ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_MODE_MAX);
+ return varyings[p_name].mode;
+}
+
+void VisualShader::set_varying_type(const String &p_name, VaryingType p_type) {
+ ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
+ ERR_FAIL_COND(!varyings.has(p_name));
+ if (varyings[p_name].type == p_type) {
+ return;
+ }
+ varyings[p_name].type = p_type;
+ _queue_update();
+}
+
+VisualShader::VaryingType VisualShader::get_varying_type(const String &p_name) {
+ ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_TYPE_MAX);
+ return varyings[p_name].type;
+}
+
void VisualShader::set_engine_version(const Dictionary &p_engine_version) {
ERR_FAIL_COND(!p_engine_version.has("major"));
ERR_FAIL_COND(!p_engine_version.has("minor"));
@@ -1072,7 +1138,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
code += "\nvoid fragment() {\n";
Set<int> processed;
- Error err = _write_node(p_type, global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
+ Error err = _write_node(p_type, &global_code, &global_code_per_node, &global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
ERR_FAIL_COND_V(err != OK, String());
switch (node->get_output_port_type(p_port)) {
@@ -1253,6 +1319,16 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
}
_queue_update();
return true;
+ } else if (name.begins_with("varyings/")) {
+ String var_name = name.get_slicec('/', 1);
+ Varying value = Varying();
+ value.name = var_name;
+ if (value.from_string(p_value) && !varyings.has(var_name)) {
+ varyings[var_name] = value;
+ varyings_list.push_back(value);
+ }
+ _queue_update();
+ return true;
} else if (name.begins_with("nodes/")) {
String typestr = name.get_slicec('/', 1);
Type type = TYPE_VERTEX;
@@ -1317,6 +1393,14 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = 0;
}
return true;
+ } else if (name.begins_with("varyings/")) {
+ String var_name = name.get_slicec('/', 1);
+ if (varyings.has(var_name)) {
+ r_ret = varyings[var_name].to_string();
+ } else {
+ r_ret = String();
+ }
+ return true;
} else if (name.begins_with("nodes/")) {
String typestr = name.get_slicec('/', 1);
Type type = TYPE_VERTEX;
@@ -1411,6 +1495,10 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "flags/" + E->get()));
}
+ for (const KeyValue<String, Varying> &E : varyings) {
+ p_list->push_back(PropertyInfo(Variant::STRING, "varyings/" + E.key));
+ }
+
for (int i = 0; i < TYPE_MAX; i++) {
for (const KeyValue<int, Node> &E : graph[i].nodes) {
String prop_name = "nodes/";
@@ -1435,7 +1523,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
-Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
+Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node;
if (vsnode->is_disabled()) {
@@ -1477,7 +1565,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (!skip_global) {
Ref<VisualShaderNodeUniform> uniform = vsnode;
if (!uniform.is_valid() || !uniform->is_global_code_generated()) {
- global_code += vsnode->generate_global(get_mode(), type, node);
+ if (global_code) {
+ *global_code += vsnode->generate_global(get_mode(), type, node);
+ }
}
String class_name = vsnode->get_class_name();
@@ -1485,9 +1575,13 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
class_name = vsnode->get_script_instance()->get_script()->get_path();
}
if (!r_classes.has(class_name)) {
- global_code_per_node += vsnode->generate_global_per_node(get_mode(), node);
+ if (global_code_per_node) {
+ *global_code_per_node += vsnode->generate_global_per_node(get_mode(), node);
+ }
for (int i = 0; i < TYPE_MAX; i++) {
- global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ if (global_code_per_func) {
+ (*global_code_per_func)[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ }
}
r_classes.insert(class_name);
}
@@ -1940,6 +2034,7 @@ void VisualShader::_update_shader() const {
Set<String> used_uniform_names;
List<VisualShaderNodeUniform *> uniforms;
Map<int, List<int>> emitters;
+ Map<int, List<int>> varying_setters;
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
@@ -1964,18 +2059,19 @@ void VisualShader::_update_shader() const {
if (uniform.is_valid()) {
uniforms.push_back(uniform.ptr());
}
+ Ref<VisualShaderNodeVaryingSetter> varying_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(E->get().node.ptr());
+ if (varying_setter.is_valid() && varying_setter->is_input_port_connected(0)) {
+ if (!varying_setters.has(i)) {
+ varying_setters.insert(i, List<int>());
+ }
+ varying_setters[i].push_back(E->key());
+ }
Ref<VisualShaderNodeParticleEmit> emit_particle = Object::cast_to<VisualShaderNodeParticleEmit>(E->get().node.ptr());
if (emit_particle.is_valid()) {
if (!emitters.has(i)) {
emitters.insert(i, List<int>());
}
-
- for (const KeyValue<int, Node> &M : graph[i].nodes) {
- if (M.value.node == emit_particle.ptr()) {
- emitters[i].push_back(M.key);
- break;
- }
- }
+ emitters[i].push_back(E->key());
}
}
}
@@ -1990,6 +2086,36 @@ void VisualShader::_update_shader() const {
}
}
+ if (!varyings.is_empty()) {
+ global_code += "\n// Varyings\n";
+
+ for (const KeyValue<String, Varying> &E : varyings) {
+ global_code += "varying ";
+ switch (E.value.type) {
+ case VaryingType::VARYING_TYPE_FLOAT:
+ global_code += "float ";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_2D:
+ global_code += "vec2 ";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_3D:
+ global_code += "vec3 ";
+ break;
+ case VaryingType::VARYING_TYPE_COLOR:
+ global_code += "vec4 ";
+ break;
+ case VaryingType::VARYING_TYPE_TRANSFORM:
+ global_code += "mat4 ";
+ break;
+ default:
+ break;
+ }
+ global_code += E.key + ";\n";
+ }
+
+ global_code += "\n";
+ }
+
Map<int, String> code_map;
Set<int> empty_funcs;
@@ -2003,12 +2129,54 @@ void VisualShader::_update_shader() const {
VMap<ConnectionKey, const List<Connection>::Element *> output_connections;
StringBuilder func_code;
+ Set<int> processed;
bool is_empty_func = false;
if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG) {
is_empty_func = true;
}
+ String varying_code;
+ if (shader_mode == Shader::MODE_SPATIAL || shader_mode == Shader::MODE_CANVAS_ITEM) {
+ for (const KeyValue<String, Varying> &E : varyings) {
+ if ((E.value.mode == VARYING_MODE_VERTEX_TO_FRAG_LIGHT && i == TYPE_VERTEX) || (E.value.mode == VARYING_MODE_FRAG_TO_LIGHT && i == TYPE_FRAGMENT)) {
+ bool found = false;
+ for (int key : varying_setters[i]) {
+ Ref<VisualShaderNodeVaryingSetter> setter = Object::cast_to<VisualShaderNodeVaryingSetter>(const_cast<VisualShaderNode *>(graph[i].nodes[key].node.ptr()));
+ if (setter.is_valid() && E.value.name == setter->get_varying_name()) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ String code2;
+ switch (E.value.type) {
+ case VaryingType::VARYING_TYPE_FLOAT:
+ code2 += "0.0";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_2D:
+ code2 += "vec2(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_3D:
+ code2 += "vec3(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_COLOR:
+ code2 += "vec4(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_TRANSFORM:
+ code2 += "mat4(1.0)";
+ break;
+ default:
+ break;
+ }
+ varying_code += vformat(" %s = %s;\n", E.key, code2);
+ }
+ is_empty_func = false;
+ }
+ }
+ }
+
for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) {
ConnectionKey from_key;
from_key.node = E->get().from_node;
@@ -2037,13 +2205,19 @@ void VisualShader::_update_shader() const {
}
insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length());
- Set<int> processed;
- Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
+ Error err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
ERR_FAIL_COND(err != OK);
+ if (varying_setters.has(i)) {
+ for (int &E : varying_setters[i]) {
+ err = _write_node(Type(i), nullptr, nullptr, nullptr, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
+ ERR_FAIL_COND(err != OK);
+ }
+ }
+
if (emitters.has(i)) {
for (int &E : emitters[i]) {
- err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
+ err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
ERR_FAIL_COND(err != OK);
}
}
@@ -2051,6 +2225,7 @@ void VisualShader::_update_shader() const {
if (shader_mode == Shader::MODE_PARTICLES) {
code_map.insert(i, func_code);
} else {
+ func_code += varying_code;
func_code += "}\n";
code += func_code;
}
@@ -2276,6 +2451,10 @@ void VisualShader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &VisualShader::set_graph_offset);
ClassDB::bind_method(D_METHOD("get_graph_offset"), &VisualShader::get_graph_offset);
+ ClassDB::bind_method(D_METHOD("add_varying", "name", "mode", "type"), &VisualShader::add_varying);
+ ClassDB::bind_method(D_METHOD("remove_varying", "name"), &VisualShader::remove_varying);
+ ClassDB::bind_method(D_METHOD("has_varying", "name"), &VisualShader::has_varying);
+
ClassDB::bind_method(D_METHOD("_update_shader"), &VisualShader::_update_shader);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset");
@@ -2295,6 +2474,17 @@ void VisualShader::_bind_methods() {
BIND_ENUM_CONSTANT(TYPE_FOG);
BIND_ENUM_CONSTANT(TYPE_MAX);
+ BIND_ENUM_CONSTANT(VARYING_MODE_VERTEX_TO_FRAG_LIGHT);
+ BIND_ENUM_CONSTANT(VARYING_MODE_FRAG_TO_LIGHT);
+ BIND_ENUM_CONSTANT(VARYING_MODE_MAX);
+
+ BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_COLOR);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_MAX);
+
BIND_CONSTANT(NODE_ID_INVALID);
BIND_CONSTANT(NODE_ID_OUTPUT);
}
@@ -2327,6 +2517,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Node3D, Vertex
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
@@ -2348,6 +2539,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Fragment
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -2374,6 +2568,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_roughness_texture", "NORMAL_ROUGHNESS_TEXTURE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "depth_texture", "DEPTH_TEXTURE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Light
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -2384,6 +2581,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "attenuation", "ATTENUATION" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "shadow_attenuation", "SHADOW_ATTENUATION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "diffuse", "DIFFUSE_LIGHT" },
@@ -2415,6 +2613,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
// Canvas Item, Fragment
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -3144,6 +3344,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" },
////////////////////////////////////////////////////////////////////////
// Node3D, Fragment.
@@ -3155,6 +3356,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular", "SPECULAR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "emission", "EMISSION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao", "AO" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" },
@@ -3170,7 +3372,10 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_scissor_threshold", "ALPHA_SCISSOR_THRESHOLD" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_hash_scale", "ALPHA_HASH_SCALE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_aa_edge", "ALPHA_ANTIALIASING_EDGE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "alpha_uv", "ALPHA_TEXTURE_COORDINATE" },
+
////////////////////////////////////////////////////////////////////////
// Node3D, Light.
////////////////////////////////////////////////////////////////////////
@@ -3294,7 +3499,7 @@ bool VisualShaderNodeOutput::is_port_separator(int p_index) const {
}
if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) {
String name = get_input_port_name(p_index);
- return bool(name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
+ return bool(name == "Ao" || name == "Normal" || name == "Rim" || name == "Clearcoat" || name == "Anisotropy" || name == "Subsurf Scatter" || name == "Alpha Scissor Threshold");
}
return false;
}
@@ -4199,3 +4404,299 @@ String VisualShaderNodeGlobalExpression::generate_global(Shader::Mode p_mode, Vi
VisualShaderNodeGlobalExpression::VisualShaderNodeGlobalExpression() {
set_editable(false);
}
+
+////////////// Varying
+
+List<VisualShaderNodeVarying::Varying> varyings;
+
+void VisualShaderNodeVarying::add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) { // static
+ varyings.push_back({ p_name, p_mode, p_type });
+}
+
+void VisualShaderNodeVarying::clear_varyings() { // static
+ varyings.clear();
+}
+
+bool VisualShaderNodeVarying::has_varying(const String &p_name) { // static
+ for (const VisualShaderNodeVarying::Varying &E : varyings) {
+ if (E.name == p_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int VisualShaderNodeVarying::get_varyings_count() const {
+ return varyings.size();
+}
+
+String VisualShaderNodeVarying::get_varying_name_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].name;
+ }
+ return "";
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_name(const String &p_name) const {
+ for (int i = 0; i < varyings.size(); i++) {
+ if (varyings[i].name == p_name) {
+ return varyings[i].type;
+ }
+ }
+ return VisualShader::VARYING_TYPE_FLOAT;
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].type;
+ }
+ return VisualShader::VARYING_TYPE_FLOAT;
+}
+
+VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_name(const String &p_name) const {
+ for (int i = 0; i < varyings.size(); i++) {
+ if (varyings[i].name == p_name) {
+ return varyings[i].mode;
+ }
+ }
+ return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
+}
+
+VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].mode;
+ }
+ return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
+}
+
+VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return get_port_type(varyings[p_idx].type, 0);
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+//////////////
+
+void VisualShaderNodeVarying::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_varying_name", "name"), &VisualShaderNodeVarying::set_varying_name);
+ ClassDB::bind_method(D_METHOD("get_varying_name"), &VisualShaderNodeVarying::get_varying_name);
+
+ ClassDB::bind_method(D_METHOD("set_varying_type", "type"), &VisualShaderNodeVarying::set_varying_type);
+ ClassDB::bind_method(D_METHOD("get_varying_type"), &VisualShaderNodeVarying::get_varying_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "varying_name"), "set_varying_name", "get_varying_name");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Vector,Transform"), "set_varying_type", "get_varying_type");
+}
+
+String VisualShaderNodeVarying::get_type_str() const {
+ switch (varying_type) {
+ case VisualShader::VARYING_TYPE_FLOAT:
+ return "float";
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ return "vec2";
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ return "vec3";
+ case VisualShader::VARYING_TYPE_COLOR:
+ return "vec4";
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ return "mat4";
+ default:
+ break;
+ }
+ return "";
+}
+
+VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualShader::VaryingType p_type, int p_port) const {
+ switch (p_type) {
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR_3D;
+ case VisualShader::VARYING_TYPE_COLOR:
+ if (p_port == 1) {
+ break; // scalar
+ }
+ return PORT_TYPE_VECTOR_3D;
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ return PORT_TYPE_TRANSFORM;
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+void VisualShaderNodeVarying::set_varying_name(String p_varying_name) {
+ if (varying_name == p_varying_name) {
+ return;
+ }
+ varying_name = p_varying_name;
+ emit_changed();
+}
+
+String VisualShaderNodeVarying::get_varying_name() const {
+ return varying_name;
+}
+
+void VisualShaderNodeVarying::set_varying_type(VisualShader::VaryingType p_varying_type) {
+ ERR_FAIL_INDEX(p_varying_type, VisualShader::VARYING_TYPE_MAX);
+ if (varying_type == p_varying_type) {
+ return;
+ }
+ varying_type = p_varying_type;
+ emit_changed();
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type() const {
+ return varying_type;
+}
+
+VisualShaderNodeVarying::VisualShaderNodeVarying() {
+}
+
+////////////// Varying Setter
+
+String VisualShaderNodeVaryingSetter::get_caption() const {
+ return vformat("VaryingSetter");
+}
+
+int VisualShaderNodeVaryingSetter::get_input_port_count() const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ return 2;
+ }
+ return 1;
+}
+
+VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_input_port_type(int p_port) const {
+ return get_port_type(varying_type, p_port);
+}
+
+String VisualShaderNodeVaryingSetter::get_input_port_name(int p_port) const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ if (p_port == 0) {
+ return "color";
+ } else {
+ return "alpha";
+ }
+ }
+ return "";
+}
+
+int VisualShaderNodeVaryingSetter::get_output_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_output_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeVaryingSetter::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeVaryingSetter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return vformat("varying %s %s;\n", get_type_str(), varying_name);
+}
+
+String VisualShaderNodeVaryingSetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ if (varying_name == "[None]") {
+ return code;
+ }
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ code += vformat(" %s = vec4(%s, %s);\n", varying_name, p_input_vars[0], p_input_vars[1]);
+ } else {
+ code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]);
+ }
+ return code;
+}
+
+VisualShaderNodeVaryingSetter::VisualShaderNodeVaryingSetter() {
+}
+
+////////////// Varying Getter
+
+String VisualShaderNodeVaryingGetter::get_caption() const {
+ return vformat("VaryingGetter");
+}
+
+int VisualShaderNodeVaryingGetter::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeVaryingGetter::get_input_port_name(int p_port) const {
+ return "";
+}
+
+int VisualShaderNodeVaryingGetter::get_output_port_count() const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ return 2;
+ }
+ return 1;
+}
+
+VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_output_port_type(int p_port) const {
+ return get_port_type(varying_type, p_port);
+}
+
+String VisualShaderNodeVaryingGetter::get_output_port_name(int p_port) const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ if (p_port == 0) {
+ return "color";
+ } else {
+ return "alpha";
+ }
+ }
+ return "";
+}
+
+bool VisualShaderNodeVaryingGetter::has_output_port_preview(int p_port) const {
+ return false;
+}
+
+String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String from = varying_name;
+ String from2;
+
+ if (varying_name == "[None]") {
+ switch (varying_type) {
+ case VisualShader::VARYING_TYPE_FLOAT:
+ from = "0.0";
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ from = "vec2(0.0)";
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ from = "vec3(0.0)";
+ break;
+ case VisualShader::VARYING_TYPE_COLOR:
+ from = "vec3(0.0)";
+ from2 = "0.0";
+ break;
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ from = "mat4(1.0)";
+ break;
+ default:
+ break;
+ }
+ } else if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ from = varying_name + ".rgb";
+ from2 = varying_name + ".a";
+ }
+
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ String code;
+ code += vformat(" %s = %s;\n", p_output_vars[0], from);
+ code += vformat(" %s = %s;\n", p_output_vars[1], from2);
+ return code;
+ }
+ return vformat(" %s = %s;\n", p_output_vars[0], from);
+}
+
+VisualShaderNodeVaryingGetter::VisualShaderNodeVaryingGetter() {
+ varying_name = "[None]";
+}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index d3b5365893..5cad5fc95b 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -73,6 +73,49 @@ public:
List<Ref<Texture2D>> params;
};
+ enum VaryingMode {
+ VARYING_MODE_VERTEX_TO_FRAG_LIGHT,
+ VARYING_MODE_FRAG_TO_LIGHT,
+ VARYING_MODE_MAX,
+ };
+
+ enum VaryingType {
+ VARYING_TYPE_FLOAT,
+ VARYING_TYPE_VECTOR_2D,
+ VARYING_TYPE_VECTOR_3D,
+ VARYING_TYPE_COLOR,
+ VARYING_TYPE_TRANSFORM,
+ VARYING_TYPE_MAX,
+ };
+
+ struct Varying {
+ String name;
+ VaryingMode mode;
+ VaryingType type;
+
+ Varying() {
+ }
+
+ Varying(String p_name, VaryingMode p_mode, VaryingType p_type) :
+ name(p_name), mode(p_mode), type(p_type) {}
+
+ bool from_string(const String &p_str) {
+ Vector<String> arr = p_str.split(",");
+ if (arr.size() != 2) {
+ return false;
+ }
+
+ mode = (VaryingMode)arr[0].to_int();
+ type = (VaryingType)arr[1].to_int();
+
+ return true;
+ }
+
+ String to_string() const {
+ return vformat("%s,%s", itos((int)mode), itos((int)type));
+ }
+ };
+
private:
Type current_type;
@@ -94,14 +137,12 @@ private:
Vector2 graph_offset;
- struct RenderModeEnums {
- Shader::Mode mode = Shader::Mode::MODE_MAX;
- const char *string;
- };
-
HashMap<String, int> modes;
Set<StringName> flags;
+ Map<String, Varying> varyings;
+ List<Varying> varyings_list;
+
mutable SafeFlag dirty;
void _queue_update();
@@ -116,7 +157,7 @@ private:
}
};
- Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const;
+ Error _write_node(Type p_type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const;
void _input_type_changed(Type p_type, int p_id);
bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const;
@@ -151,6 +192,18 @@ public:
void add_node(Type p_type, const Ref<VisualShaderNode> &p_node, const Vector2 &p_position, int p_id);
void set_node_position(Type p_type, int p_id, const Vector2 &p_position);
+ void add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type);
+ void remove_varying(const String &p_name);
+ bool has_varying(const String &p_name) const;
+ int get_varyings_count() const;
+ const Varying *get_varying_by_index(int p_idx) const;
+
+ void set_varying_mode(const String &p_name, VaryingMode p_mode);
+ VaryingMode get_varying_mode(const String &p_name);
+
+ void set_varying_type(const String &p_name, VaryingType p_type);
+ VaryingType get_varying_type(const String &p_name);
+
Vector2 get_node_position(Type p_type, int p_id) const;
Ref<VisualShaderNode> get_node(Type p_type, int p_id) const;
@@ -190,6 +243,8 @@ public:
};
VARIANT_ENUM_CAST(VisualShader::Type)
+VARIANT_ENUM_CAST(VisualShader::VaryingMode)
+VARIANT_ENUM_CAST(VisualShader::VaryingType)
///
///
///
@@ -697,6 +752,103 @@ public:
VisualShaderNodeGlobalExpression();
};
+class VisualShaderNodeVarying : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeVarying, VisualShaderNode);
+
+public:
+ struct Varying {
+ String name;
+ VisualShader::VaryingMode mode;
+ VisualShader::VaryingType type;
+ bool assigned = false;
+ };
+
+protected:
+ VisualShader::VaryingType varying_type = VisualShader::VARYING_TYPE_FLOAT;
+ String varying_name = "[None]";
+
+public: // internal
+ static void add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type);
+ static void clear_varyings();
+ static bool has_varying(const String &p_name);
+
+ int get_varyings_count() const;
+ String get_varying_name_by_index(int p_idx) const;
+ VisualShader::VaryingMode get_varying_mode_by_name(const String &p_name) const;
+ VisualShader::VaryingMode get_varying_mode_by_index(int p_idx) const;
+ VisualShader::VaryingType get_varying_type_by_name(const String &p_name) const;
+ VisualShader::VaryingType get_varying_type_by_index(int p_idx) const;
+ PortType get_port_type_by_index(int p_idx) const;
+
+protected:
+ static void _bind_methods();
+
+protected:
+ String get_type_str() const;
+ PortType get_port_type(VisualShader::VaryingType p_type, int p_port) const;
+
+public:
+ virtual String get_caption() const override = 0;
+
+ virtual int get_input_port_count() const override = 0;
+ virtual PortType get_input_port_type(int p_port) const override = 0;
+ virtual String get_input_port_name(int p_port) const override = 0;
+
+ virtual int get_output_port_count() const override = 0;
+ virtual PortType get_output_port_type(int p_port) const override = 0;
+ virtual String get_output_port_name(int p_port) const override = 0;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0;
+
+ void set_varying_name(String p_varying_name);
+ String get_varying_name() const;
+
+ void set_varying_type(VisualShader::VaryingType p_varying_type);
+ VisualShader::VaryingType get_varying_type() const;
+
+ VisualShaderNodeVarying();
+};
+
+class VisualShaderNodeVaryingSetter : public VisualShaderNodeVarying {
+ GDCLASS(VisualShaderNodeVaryingSetter, VisualShaderNodeVarying);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeVaryingSetter();
+};
+
+class VisualShaderNodeVaryingGetter : public VisualShaderNodeVarying {
+ GDCLASS(VisualShaderNodeVaryingGetter, VisualShaderNodeVarying);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+ virtual bool has_output_port_preview(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeVaryingGetter();
+};
+
extern String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name);
#endif // VISUAL_SHADER_H