summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editor/icons/RibbonTrailMesh.svg1
-rw-r--r--editor/icons/TubeTrailMesh.svg1
-rw-r--r--platform/javascript/export/export.cpp2
-rw-r--r--scene/2d/light_2d.cpp4
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/animation/animation_node_state_machine.cpp2
-rw-r--r--scene/gui/aspect_ratio_container.cpp2
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/control.cpp4
-rw-r--r--scene/gui/graph_node.cpp2
-rw-r--r--scene/gui/label.cpp2
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/link_button.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/text_edit.cpp2
-rw-r--r--scene/gui/tree.cpp2
-rw-r--r--scene/main/canvas_item.cpp4
-rw-r--r--scene/main/node.cpp2
-rw-r--r--scene/main/viewport.cpp4
-rw-r--r--scene/main/window.cpp6
-rw-r--r--scene/resources/material.cpp11
-rw-r--r--scene/resources/particles_material.cpp2
-rw-r--r--scene/resources/text_line.cpp2
-rw-r--r--scene/resources/text_paragraph.cpp2
-rw-r--r--scene/resources/tile_set.cpp2
-rw-r--r--scene/resources/visual_shader_nodes.cpp16
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp2
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp59
-rw-r--r--servers/rendering/shader_language.cpp1187
-rw-r--r--servers/rendering/shader_language.h61
32 files changed, 960 insertions, 440 deletions
diff --git a/editor/icons/RibbonTrailMesh.svg b/editor/icons/RibbonTrailMesh.svg
new file mode 100644
index 0000000000..3f6cf0bfef
--- /dev/null
+++ b/editor/icons/RibbonTrailMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f" stroke-width=".25" transform="rotate(90)"><path d="m6.5625-14.062499h1.875v13.124999h-1.875z"/><path d="m.9375-11.249999h1.875v7.499999h-1.875z"/><path d="m12.187499-11.249999h1.875v7.5h-1.875z"/></g></svg>
diff --git a/editor/icons/TubeTrailMesh.svg b/editor/icons/TubeTrailMesh.svg
new file mode 100644
index 0000000000..3ca524226f
--- /dev/null
+++ b/editor/icons/TubeTrailMesh.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 14.999999 14.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f"><path d="m14.0625 7.5c0-1.6377-.2123-3.12-.5969-4.2737-.1923-.57682-.4237-1.0754-.7508-1.4905-.3271-.41505-.8259-.79834-1.4648-.79834h-7.5c-.6389 0-1.1396.38329-1.4667.79834s-.5585.91366-.7507 1.4905c-.3846 1.1536-.5951 2.6359-.5951 4.2737s.2105 3.12.5951 4.2737c.1922.57682.4236 1.0754.7507 1.4905.3271.41505.8278.79834 1.4667.79834h7.5c.6389 0 1.1377-.38329 1.4648-.79834s.5585-.91366.7508-1.4905c.3846-1.1536.5969-2.6359.5969-4.2737zm-2.8125-4.6875002c.4358 1.0052002 0 0 .4358 1.0052002.2941.88221.5017 2.2134.5017 3.6823s-.2076 2.8-.5017 3.6823c-.1449.4347 0 0-.4358 1.005199l-7.5.000041c-.1212-.15705-.2929-.57092-.4376-1.0052-.2941-.88221-.4999-2.2134-.4999-3.6823s.2058-2.8.4999-3.6823c.1447-.43433.3164-.8482.4376-1.0052"/><path d="m6.5625-11.25h1.875v7.5h-1.875z" stroke-width=".25" transform="rotate(90)"/></g></svg>
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index e398072312..154f129874 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -651,7 +651,7 @@ void EditorExportPlatformJavaScript::get_export_options(List<ExportOption> *r_op
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "html/experimental_virtual_keyboard"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "progressive_web_app/enabled"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/offline_page", PROPERTY_HINT_FILE, "*.html"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/display", PROPERTY_HINT_ENUM, "Fullscreen,Standalone,Minimal Ui,Browser"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/display", PROPERTY_HINT_ENUM, "Fullscreen,Standalone,Minimal UI,Browser"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "progressive_web_app/orientation", PROPERTY_HINT_ENUM, "Any,Landscape,Portrait"), 0));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_144x144", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "progressive_web_app/icon_180x180", PROPERTY_HINT_FILE, "*.png,*.webp,*.svg,*.svgz"), ""));
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 8fb765f16b..ce57895341 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -281,7 +281,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Add,Subtract,Mix"), "set_blend_mode", "get_blend_mode");
ADD_GROUP("Range", "range_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max");
@@ -292,7 +292,7 @@ void Light2D::_bind_methods() {
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow_enabled", "is_shadow_enabled");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF5,PCF13"), "set_shadow_filter", "get_shadow_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None (Fast),PCF5 (Average),PCF13 (Slow)"), "set_shadow_filter", "get_shadow_filter");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 72392be5bd..55b26bc9fb 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -962,7 +962,7 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stream_playback"), &AudioStreamPlayer3D::get_stream_playback);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,Inverse Square,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index ad24f39bce..7762156b4a 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -230,7 +230,7 @@ void ReflectionProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &ReflectionProbe::set_update_mode);
ClassDB::bind_method(D_METHOD("get_update_mode"), &ReflectionProbe::get_update_mode);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once,Always"), "set_update_mode", "get_update_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_EXP_RANGE, "0,16384,0.1,or_greater"), "set_max_distance", "get_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
@@ -242,7 +242,7 @@ void ReflectionProbe::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
ADD_GROUP("Ambient", "ambient_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,Constant Color"), "set_ambient_mode", "get_ambient_mode");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ambient_color", "get_ambient_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_color_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_color_energy", "get_ambient_color_energy");
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 246fff6d57..65918a2989 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -115,7 +115,7 @@ void AnimationNodeStateMachineTransition::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_priority", "priority"), &AnimationNodeStateMachineTransition::set_priority);
ClassDB::bind_method(D_METHOD("get_priority"), &AnimationNodeStateMachineTransition::get_priority);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,AtEnd"), "set_switch_mode", "get_switch_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "switch_mode", PROPERTY_HINT_ENUM, "Immediate,Sync,At End"), "set_switch_mode", "get_switch_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_advance"), "set_auto_advance", "has_auto_advance");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "advance_condition"), "set_advance_condition", "get_advance_condition");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "xfade_time", PROPERTY_HINT_RANGE, "0,240,0.01"), "set_xfade_time", "get_xfade_time");
diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp
index c7f6c0e2da..fb6fa9dec9 100644
--- a/scene/gui/aspect_ratio_container.cpp
+++ b/scene/gui/aspect_ratio_container.cpp
@@ -155,7 +155,7 @@ void AspectRatioContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_alignment_vertical"), &AspectRatioContainer::get_alignment_vertical);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio"), "set_ratio", "get_ratio");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width controls height,Height controls width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width Controls Height,Height Controls Width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
ADD_GROUP("Alignment", "alignment_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alignment_horizontal", PROPERTY_HINT_ENUM, "Begin,Center,End"), "set_alignment_horizontal", "get_alignment_horizontal");
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index b0bcde8865..c0df5271b4 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -533,7 +533,7 @@ void Button::_bind_methods() {
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 83abd02b40..0ae1dec46d 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2801,7 +2801,7 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction");
ADD_GROUP("Layout Direction", "layout_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-right,Right-to-left"), "set_layout_direction", "get_layout_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction");
ADD_GROUP("Rect", "rect_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
@@ -2828,7 +2828,7 @@ void Control::_bind_methods() {
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,Ibeam,Pointing hand,Cross,Wait,Busy,Drag,Can drop,Forbidden,Vertical resize,Horizontal resize,Secondary diagonal resize,Main diagonal resize,Move,Vertical split,Horizontal split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_default_cursor_shape", PROPERTY_HINT_ENUM, "Arrow,I-Beam,Pointing Hand,Cross,Wait,Busy,Drag,Can Drop,Forbidden,Vertical Resize,Horizontal Resize,Secondary Diagonal Resize,Main Diagonal Resize,Move,Vertical Split,Horizontal Split,Help"), "set_default_cursor_shape", "get_default_cursor_shape");
ADD_GROUP("Size Flags", "size_flags_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill,Expand,Shrink Center,Shrink End"), "set_h_size_flags", "get_h_size_flags");
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 1ca54a16ae..77c502cf8d 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -999,7 +999,7 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_overlay"), &GraphNode::get_overlay);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset"), "set_position_offset", "get_position_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index be73fd8f51..de0ee626b9 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -695,7 +695,7 @@ void Label::_bind_methods() {
BIND_ENUM_CONSTANT(VALIGN_FILL);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_align", "get_align");
ADD_PROPERTY(PropertyInfo(Variant::INT, "valign", PROPERTY_HINT_ENUM, "Top,Center,Bottom,Fill"), "set_valign", "get_valign");
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 98dd9f624b..c2ed9c1a3c 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -2209,7 +2209,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 1f7b61e3d1..d45ffde715 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -292,7 +292,7 @@ void LinkButton::_bind_methods() {
BIND_ENUM_CONSTANT(UNDERLINE_MODE_NEVER);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::INT, "underline", PROPERTY_HINT_ENUM, "Always,On Hover,Never"), "set_underline_mode", "get_underline_mode");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 2800ab0442..9ed4c937f4 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -3935,7 +3935,7 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_ARRAY_TYPE, "RichTextEffect", (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE)), "set_effects", "get_effects");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_GROUP("Structured Text", "structured_text_");
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 13ff2c5b86..df4cf9a740 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -353,7 +353,7 @@ void SplitContainer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "split_offset"), "set_split_offset", "get_split_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collapsed"), "set_collapsed", "is_collapsed");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden & Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "dragger_visibility", PROPERTY_HINT_ENUM, "Visible,Hidden,Hidden and Collapsed"), "set_dragger_visibility", "get_dragger_visibility");
BIND_ENUM_CONSTANT(DRAGGER_VISIBLE);
BIND_ENUM_CONSTANT(DRAGGER_HIDDEN);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index d19d95f6f4..4b199d1441 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -7055,7 +7055,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_minimap_width"), &TextEdit::get_minimap_width);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly");
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 2f78736a12..927dce7988 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -4386,7 +4386,7 @@ void Tree::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_rmb_select"), "set_allow_rmb_select", "get_allow_rmb_select");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_folding"), "set_hide_folding", "is_folding_hidden");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_root"), "set_hide_root", "is_root_hidden");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In between"), "set_drop_mode_flags", "get_drop_mode_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "drop_mode_flags", PROPERTY_HINT_FLAGS, "On Item,In Between"), "set_drop_mode_flags", "get_drop_mode_flags");
ADD_PROPERTY(PropertyInfo(Variant::INT, "select_mode", PROPERTY_HINT_ENUM, "Single,Row,Multi"), "set_select_mode", "get_select_mode");
ADD_SIGNAL(MethodInfo("item_selected"));
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index d594c6c8b6..181fe606c8 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -271,7 +271,7 @@ void CanvasItemMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "loop"), &CanvasItemMaterial::set_particles_anim_loop);
ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &CanvasItemMaterial::get_particles_anim_loop);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,Premult Alpha"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Premultiplied Alpha"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_animation"), "set_particles_animation", "get_particles_animation");
@@ -1554,7 +1554,7 @@ void CanvasTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "specular_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_specular_color", "get_specular_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "specular_shininess", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_specular_shininess", "get_specular_shininess");
ADD_GROUP("Texture", "texture_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Aniso.,Linear Mipmap Aniso."), "set_texture_filter", "get_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat");
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index c90d3e4a32..dc7057f339 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2872,7 +2872,7 @@ void Node::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer", "get_custom_multiplayer");
ADD_GROUP("Process", "process_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,WhenPaused,Always,Disabled"), "set_process_mode", "get_process_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority");
ADD_GROUP("Editor Description", "editor_");
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 62e1223fb0..77667cf188 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3601,8 +3601,8 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled,FXAA"), "set_screen_space_aa", "get_screen_space_aa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"), "set_msaa", "get_msaa");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_occlusion_culling"), "set_use_occlusion_culling", "is_using_occlusion_culling");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_threshold", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_lod_threshold", "get_lod_threshold");
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index b7bc2a83c5..d793be1869 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1444,7 +1444,7 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,FullScreen"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen");
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
@@ -1461,8 +1461,8 @@ void Window::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size");
ADD_GROUP("Content Scale", "content_scale_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,CanvasItems,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Canvas Items,Viewport"), "set_content_scale_mode", "get_content_scale_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
ADD_GROUP("Theme", "theme_");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_custom_type"), "set_theme_custom_type", "get_theme_custom_type");
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 75dd417f7f..100fccc783 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -1760,7 +1760,8 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
if (orm) {
if (property.name == "shading_mode") {
- property.hint_string = "Unshaded,PerPixel"; //vertex not supported in ORM mode, since no individual roughness.
+ // Vertex not supported in ORM mode, since no individual roughness.
+ property.hint_string = "Unshaded,Per-Pixel";
}
if (property.name.begins_with("roughness") || property.name.begins_with("metallic") || property.name.begins_with("ao_texture")) {
property.usage = 0;
@@ -2387,18 +2388,18 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &BaseMaterial3D::get_distance_fade_min_distance);
ADD_GROUP("Transparency", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth PrePass"), "set_transparency", "get_transparency");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "transparency", PROPERTY_HINT_ENUM, "Disabled,Alpha,Alpha Scissor,Alpha Hash,Depth Pre-Pass"), "set_transparency", "get_transparency");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_hash_scale", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_alpha_hash_scale", "get_alpha_hash_scale");
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_antialiasing_mode", PROPERTY_HINT_ENUM, "Disabled,Alpha Edge Blend,Alpha Edge Clip"), "set_alpha_antialiasing", "get_alpha_antialiasing");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_antialiasing_edge", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_antialiasing_edge", "get_alpha_antialiasing_edge");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_blend_mode", "get_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never"), "set_depth_draw_mode", "get_depth_draw_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_flag", "get_flag", FLAG_DISABLE_DEPTH_TEST);
ADD_GROUP("Shading", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,PerPixel,PerVertex"), "set_shading_mode", "get_shading_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shading_mode", PROPERTY_HINT_ENUM, "Unshaded,Per-Pixel,Per-Vertex"), "set_shading_mode", "get_shading_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT);
@@ -2502,7 +2503,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Detail", "detail_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "detail_enabled"), "set_feature", "get_feature", FEATURE_DETAIL);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_mask", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_MASK);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_detail_blend_mode", "get_detail_blend_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply"), "set_detail_blend_mode", "get_detail_blend_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "detail_uv_layer", PROPERTY_HINT_ENUM, "UV1,UV2"), "set_detail_uv", "get_detail_uv");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_albedo", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_ALBEDO);
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "detail_normal", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_DETAIL_NORMAL);
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index a965317c81..60d5566f08 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -1316,7 +1316,7 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET);
ADD_GROUP("Sub Emitter", "sub_emitter_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,AtEnd,AtCollision"), "set_sub_emitter_mode", "get_sub_emitter_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,At End,At Collision"), "set_sub_emitter_mode", "get_sub_emitter_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_sub_emitter_frequency", "get_sub_emitter_frequency");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity");
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index 925867a1f2..f1eff6e84f 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -74,7 +74,7 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextLine::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &TextLine::get_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida justification,Word justification,Trim edge spaces after justification,Justification only after last tab"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab"), "set_flags", "get_flags");
ClassDB::bind_method(D_METHOD("get_objects"), &TextLine::get_objects);
ClassDB::bind_method(D_METHOD("get_object_rect", "key"), &TextLine::get_object_rect);
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 341f5abd80..958c94fe31 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -72,7 +72,7 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_flags", "flags"), &TextParagraph::set_flags);
ClassDB::bind_method(D_METHOD("get_flags"), &TextParagraph::get_flags);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida justification,Word justification,Trim edge spaces after justification,Justification only after last tab,Break mandatory,Break words,Break graphemes"), "set_flags", "get_flags");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Kashida Justify,Word Justify,Trim Edge Spaces After Justify,Justify Only After Last Tab,Break Mandatory,Break Words,Break Graphemes"), "set_flags", "get_flags");
ClassDB::bind_method(D_METHOD("set_width", "width"), &TextParagraph::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &TextParagraph::get_width);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 9db7acb263..308f219a8d 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -1290,7 +1290,7 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tile_skew", "skew"), &TileSet::set_tile_skew);
ClassDB::bind_method(D_METHOD("get_tile_skew"), &TileSet::get_tile_skew);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-offset square,Hexagon"), "set_tile_shape", "get_tile_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_shape", PROPERTY_HINT_ENUM, "Square,Isometric,Half-Offset Square,Hexagon"), "set_tile_shape", "get_tile_shape");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_layout", PROPERTY_HINT_ENUM, "Stacked,Stacked Offset,Stairs Right,Stairs Down,Diamond Right,Diamond Down"), "set_tile_layout", "get_tile_layout");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tile_offset_axis", PROPERTY_HINT_ENUM, "Horizontal Offset,Vertical Offset"), "set_tile_offset_axis", "get_tile_offset_axis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "tile_size"), "set_tile_size", "get_tile_size");
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 7943b95177..c2a6ad72d7 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -775,7 +775,7 @@ void VisualShaderNodeTexture::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,Screen,Texture2D,NormalMap2D,Depth,SamplerPort"), "set_source", "get_source");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type");
BIND_ENUM_CONSTANT(SOURCE_TEXTURE);
BIND_ENUM_CONSTANT(SOURCE_SCREEN);
@@ -1308,7 +1308,7 @@ void VisualShaderNodeCubemap::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "cube_map", PROPERTY_HINT_RESOURCE_TYPE, "Cubemap"), "set_cube_map", "get_cube_map");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map"), "set_texture_type", "get_texture_type");
BIND_ENUM_CONSTANT(SOURCE_TEXTURE);
BIND_ENUM_CONSTANT(SOURCE_PORT);
@@ -1409,7 +1409,7 @@ void VisualShaderNodeFloatOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeFloatOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeFloatOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Atan2,Step"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,ATan2,Step"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1506,7 +1506,7 @@ void VisualShaderNodeIntOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeIntOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeIntOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Max,Min"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1615,7 +1615,7 @@ void VisualShaderNodeVectorOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeVectorOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeVectorOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Sub,Multiply,Divide,Remainder,Power,Max,Min,Cross,Atan2,Reflect,Step"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Add,Subtract,Multiply,Divide,Remainder,Power,Max,Min,Cross,ATan2,Reflect,Step"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_ADD);
BIND_ENUM_CONSTANT(OP_SUB);
@@ -1785,7 +1785,7 @@ void VisualShaderNodeColorOp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_operator", "op"), &VisualShaderNodeColorOp::set_operator);
ClassDB::bind_method(D_METHOD("get_operator"), &VisualShaderNodeColorOp::get_operator);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,SoftLight,HardLight"), "set_operator", "get_operator");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "operator", PROPERTY_HINT_ENUM, "Screen,Difference,Darken,Lighten,Overlay,Dodge,Burn,Soft Light,Hard Light"), "set_operator", "get_operator");
BIND_ENUM_CONSTANT(OP_SCREEN);
BIND_ENUM_CONSTANT(OP_DIFFERENCE);
@@ -3899,7 +3899,7 @@ void VisualShaderNodeIntUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntUniform::set_default_value);
ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntUniform::get_default_value);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range+Step"), "set_hint", "get_hint");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step"), "set_hint", "get_hint");
ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max"), "set_max", "get_max");
ADD_PROPERTY(PropertyInfo(Variant::INT, "step"), "set_step", "get_step");
@@ -4487,7 +4487,7 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_color_default", "type"), &VisualShaderNodeTextureUniform::set_color_default);
ClassDB::bind_method(D_METHOD("get_color_default"), &VisualShaderNodeTextureUniform::get_color_default);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normalmap,Aniso"), "set_texture_type", "get_texture_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_type", PROPERTY_HINT_ENUM, "Data,Color,Normal Map,Anisotropic"), "set_texture_type", "get_texture_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "color_default", PROPERTY_HINT_ENUM, "White Default,Black Default"), "set_color_default", "get_color_default");
BIND_ENUM_CONSTANT(TYPE_DATA);
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index 06d51776a3..5c076ca3fe 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -159,7 +159,7 @@ void AudioEffectDistortion::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_post_gain", "post_gain"), &AudioEffectDistortion::set_post_gain);
ClassDB::bind_method(D_METHOD("get_post_gain"), &AudioEffectDistortion::get_post_gain);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,WaveShape"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 3a000bd06e..056c8113a7 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -391,10 +391,21 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
String header;
if (fnode->return_type == SL::TYPE_STRUCT) {
- header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "(";
+ header = _mkid(fnode->return_struct_name);
} else {
- header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "(";
+ header = _typestr(fnode->return_type);
}
+
+ if (fnode->return_array_size > 0) {
+ header += "[";
+ header += itos(fnode->return_array_size);
+ header += "]";
+ }
+
+ header += " ";
+ header += _mkid(fnode->name);
+ header += "(";
+
for (int i = 0; i < fnode->arguments.size(); i++) {
if (i > 0) {
header += ", ";
@@ -407,6 +418,11 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S
} else {
header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name);
}
+ if (fnode->arguments[i].array_size > 0) {
+ header += "[";
+ header += itos(fnode->arguments[i].array_size);
+ header += "]";
+ }
}
header += ")\n";
@@ -959,25 +975,30 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
declaration += itos(adnode->declarations[i].size);
}
declaration += "]";
- int sz = adnode->declarations[i].initializer.size();
- if (sz > 0) {
+ if (adnode->declarations[i].single_expression) {
declaration += "=";
- if (adnode->datatype == SL::TYPE_STRUCT) {
- declaration += _mkid(adnode->struct_name);
- } else {
- declaration += _typestr(adnode->datatype);
- }
- declaration += "[";
- declaration += itos(sz);
- declaration += "]";
- declaration += "(";
- for (int j = 0; j < sz; j++) {
- declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (j != sz - 1) {
- declaration += ", ";
+ declaration += _dump_node_code(adnode->declarations[i].initializer[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ } else {
+ int sz = adnode->declarations[i].initializer.size();
+ if (sz > 0) {
+ declaration += "=";
+ if (adnode->datatype == SL::TYPE_STRUCT) {
+ declaration += _mkid(adnode->struct_name);
+ } else {
+ declaration += _typestr(adnode->datatype);
+ }
+ declaration += "[";
+ declaration += itos(sz);
+ declaration += "]";
+ declaration += "(";
+ for (int j = 0; j < sz; j++) {
+ declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
+ if (j != sz - 1) {
+ declaration += ", ";
+ }
}
+ declaration += ")";
}
- declaration += ")";
}
}
@@ -988,7 +1009,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
bool use_fragment_varying = false;
if (!(p_actions.entry_point_stages.has(current_func_name) && p_actions.entry_point_stages[current_func_name] == STAGE_VERTEX)) {
- if (anode->assign_expression != nullptr) {
+ if (anode->assign_expression != nullptr && shader->varyings.has(anode->name)) {
use_fragment_varying = true;
} else {
if (p_assigning) {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 2ce7707257..14b21e1f42 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -926,6 +926,8 @@ void ShaderLanguage::clear() {
char_idx = 0;
error_set = false;
error_str = "";
+ last_const = false;
+ pass_array = false;
while (nodes) {
Node *n = nodes;
nodes = nodes->next;
@@ -973,7 +975,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_BUILTIN_VAR;
}
-
return true;
}
@@ -987,7 +988,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
-
return true;
}
@@ -1004,16 +1004,15 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_array_size) {
*r_array_size = p_block->variables[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_LOCAL_VAR;
- }
if (r_struct_name) {
*r_struct_name = p_block->variables[p_identifier].struct_name;
}
if (r_constant_value) {
*r_constant_value = p_block->variables[p_identifier].value;
}
-
+ if (r_type) {
+ *r_type = IDENTIFIER_LOCAL_VAR;
+ }
return true;
}
@@ -1035,15 +1034,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = function->arguments[i].type;
}
- if (r_type) {
- *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
- }
if (r_struct_name) {
*r_struct_name = function->arguments[i].type_str;
}
+ if (r_array_size) {
+ *r_array_size = function->arguments[i].array_size;
+ }
if (r_is_const) {
*r_is_const = function->arguments[i].is_const;
}
+ if (r_type) {
+ *r_type = IDENTIFIER_FUNCTION_ARGUMENT;
+ }
return true;
}
}
@@ -1082,9 +1084,6 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_array_size) {
*r_array_size = shader->constants[p_identifier].array_size;
}
- if (r_type) {
- *r_type = IDENTIFIER_CONSTANT;
- }
if (r_struct_name) {
*r_struct_name = shader->constants[p_identifier].type_str;
}
@@ -1093,6 +1092,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
*r_constant_value = shader->constants[p_identifier].initializer->values[0];
}
}
+ if (r_type) {
+ *r_type = IDENTIFIER_CONSTANT;
+ }
return true;
}
@@ -1105,6 +1107,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (r_data_type) {
*r_data_type = shader->functions[i].function->return_type;
}
+ if (r_array_size) {
+ *r_array_size = shader->functions[i].function->return_array_size;
+ }
if (r_type) {
*r_type = IDENTIFIER_FUNCTION;
}
@@ -1115,13 +1120,18 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
return false;
}
-bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) {
+bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type, int *r_ret_size) {
bool valid = false;
DataType ret_type = TYPE_VOID;
+ int ret_size = 0;
switch (p_op->op) {
case OP_EQUAL:
case OP_NOT_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
valid = na == nb;
@@ -1131,6 +1141,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_LESS_EQUAL:
case OP_GREATER:
case OP_GREATER_EQUAL: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1140,6 +1154,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_AND:
case OP_OR: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1148,6 +1166,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
} break;
case OP_NOT: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na == TYPE_BOOL;
ret_type = TYPE_BOOL;
@@ -1158,6 +1180,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_POST_INCREMENT:
case OP_POST_DECREMENT:
case OP_NEGATE: {
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na > TYPE_BOOL && na < TYPE_MAT2;
ret_type = na;
@@ -1166,6 +1192,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_SUB:
case OP_MUL:
case OP_DIV: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1234,6 +1264,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* component-wise.
*/
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1286,6 +1320,10 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
case OP_ASSIGN_SHIFT_RIGHT:
case OP_SHIFT_LEFT:
case OP_SHIFT_RIGHT: {
+ if ((!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) || (!p_op->arguments[1]->is_indexed() && p_op->arguments[1]->get_array_size() > 0)) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1334,6 +1372,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_ASSIGN: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
if (na == TYPE_STRUCT || nb == TYPE_STRUCT) {
@@ -1342,11 +1392,24 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
valid = na == nb;
}
ret_type = na;
+ ret_size = sa;
} break;
case OP_ASSIGN_ADD:
case OP_ASSIGN_SUB:
case OP_ASSIGN_MUL:
case OP_ASSIGN_DIV: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1414,6 +1477,18 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
* must match.
*/
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[0]->is_indexed()) {
+ sa = p_op->arguments[0]->get_array_size();
+ }
+ if (!p_op->arguments[1]->is_indexed()) {
+ sb = p_op->arguments[1]->get_array_size();
+ }
+ if (sa > 0 || sb > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
@@ -1468,17 +1543,34 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
}
} break;
case OP_BIT_INVERT: { //unaries
+ if (!p_op->arguments[0]->is_indexed() && p_op->arguments[0]->get_array_size() > 0) {
+ break; // don't accept arrays
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
valid = na >= TYPE_INT && na < TYPE_FLOAT;
ret_type = na;
} break;
case OP_SELECT_IF: {
+ int sa = 0;
+ int sb = 0;
+ if (!p_op->arguments[1]->is_indexed()) {
+ sa = p_op->arguments[1]->get_array_size();
+ }
+ if (!p_op->arguments[2]->is_indexed()) {
+ sb = p_op->arguments[2]->get_array_size();
+ }
+ if (sa != sb) {
+ break; // don't accept arrays if their sizes are not equal
+ }
+
DataType na = p_op->arguments[0]->get_datatype();
DataType nb = p_op->arguments[1]->get_datatype();
DataType nc = p_op->arguments[2]->get_datatype();
valid = na == TYPE_BOOL && (nb == nc);
ret_type = nb;
+ ret_size = sa;
} break;
default: {
ERR_FAIL_V(false);
@@ -1488,6 +1580,9 @@ bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type
if (r_ret_type) {
*r_ret_type = ret_type;
}
+ if (r_ret_size) {
+ *r_ret_size = ret_size;
+ }
return valid;
}
@@ -2223,6 +2318,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
Vector<DataType> args;
Vector<StringName> args2;
+ Vector<int> args3;
ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false);
@@ -2231,6 +2327,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
for (int i = 1; i < p_func->arguments.size(); i++) {
args.push_back(p_func->arguments[i]->get_datatype());
args2.push_back(p_func->arguments[i]->get_datatype_name());
+ args3.push_back(p_func->arguments[i]->get_array_size());
}
int argcount = args.size();
@@ -2498,6 +2595,11 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
arg_list += func_arg_name;
}
}
@@ -2510,21 +2612,32 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool fail = false;
for (int j = 0; j < args.size(); j++) {
- if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
+ if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && args3[j] == 0 && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) {
//all good, but it needs implicit conversion later
- } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str)) {
+ } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) || args3[j] != pfunc->arguments[j].array_size) {
String func_arg_name;
if (pfunc->arguments[j].type == TYPE_STRUCT) {
func_arg_name = pfunc->arguments[j].type_str;
} else {
func_arg_name = get_datatype_name(pfunc->arguments[j].type);
}
+ if (pfunc->arguments[j].array_size > 0) {
+ func_arg_name += "[";
+ func_arg_name += itos(pfunc->arguments[j].array_size);
+ func_arg_name += "]";
+ }
String arg_name;
if (args[j] == TYPE_STRUCT) {
arg_name = args2[j];
} else {
arg_name = get_datatype_name(args[j]);
}
+ if (args3[j] > 0) {
+ arg_name += "[";
+ arg_name += itos(args3[j]);
+ arg_name += "]";
+ }
+
_set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name));
fail = true;
break;
@@ -2570,16 +2683,45 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
return false;
}
-bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const {
- if (a->get_datatype() != b->get_datatype()) {
- return false;
+bool ShaderLanguage::_compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b) {
+ bool result = true;
+
+ if (p_datatype_a == TYPE_STRUCT || p_datatype_b == TYPE_STRUCT) {
+ if (p_datatype_name_a != p_datatype_name_b) {
+ result = false;
+ }
+ } else {
+ if (p_datatype_a != p_datatype_b) {
+ result = false;
+ }
}
- if (a->get_datatype() == TYPE_STRUCT || b->get_datatype() == TYPE_STRUCT) {
- if (a->get_datatype_name() != b->get_datatype_name()) {
- return false;
+
+ if (p_array_size_a != p_array_size_b) {
+ result = false;
+ }
+
+ if (!result) {
+ String type_name = p_datatype_a == TYPE_STRUCT ? p_datatype_name_a : get_datatype_name(p_datatype_a);
+ if (p_array_size_a > 0) {
+ type_name += "[";
+ type_name += itos(p_array_size_a);
+ type_name += "]";
}
+
+ String type_name2 = p_datatype_b == TYPE_STRUCT ? p_datatype_name_b : get_datatype_name(p_datatype_b);
+ if (p_array_size_b > 0) {
+ type_name2 += "[";
+ type_name2 += itos(p_array_size_b);
+ type_name2 += "]";
+ }
+
+ _set_error("Invalid assignment of '" + type_name2 + "' to '" + type_name + "'");
}
- return true;
+ return result;
+}
+
+bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) {
+ return _compare_datatypes(a->get_datatype(), a->get_datatype_name(), a->get_array_size(), b->get_datatype(), b->get_datatype_name(), b->get_array_size());
}
bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg) {
@@ -3390,11 +3532,12 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa
ERR_FAIL_V(false); //bug? function not found
}
-ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info) {
DataType type = TYPE_VOID;
String struct_name = "";
int array_size = 0;
bool auto_size = false;
+ bool undefined_size = false;
Token tk = _get_token();
if (tk.type == TK_CURLY_BRACKET_OPEN) {
@@ -3415,6 +3558,137 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
TkPos pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_BRACKET_CLOSE) {
+ undefined_size = true;
+ tk = _get_token();
+ } else {
+ _set_tkpos(pos);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size = cnode->values[0].sint;
+ if (array_size <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return nullptr;
+ }
+
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ } else {
+ tk = _get_token();
+ }
+ }
+ } else {
+ _set_error("Expected '['");
+ return nullptr;
+ }
+ }
+
+ ArrayConstructNode *an = alloc_node<ArrayConstructNode>();
+
+ if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization
+ int idx = 0;
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return nullptr;
+ }
+
+ // define type by using the first member
+ if (auto_size && idx == 0) {
+ type = n->get_datatype();
+ if (type == TYPE_STRUCT) {
+ struct_name = n->get_datatype_name();
+ }
+ } else {
+ if (!_compare_datatypes(type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return nullptr;
+ }
+ }
+
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ an->initializer.push_back(n);
+ } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ an->initializer.push_back(n);
+ break;
+ } else {
+ if (auto_size) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return nullptr;
+ }
+ idx++;
+ }
+ if (!auto_size && !undefined_size && an->initializer.size() != array_size) {
+ _set_error("Array size mismatch");
+ return nullptr;
+ }
+ } else {
+ _set_error("Expected array initialization!");
+ return nullptr;
+ }
+
+ an->datatype = type;
+ an->struct_name = struct_name;
+ return an;
+}
+
+ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size) {
+ DataType type = TYPE_VOID;
+ String struct_name = "";
+ int array_size = 0;
+ bool auto_size = false;
+ TkPos prev_pos = _get_tkpos();
+ Token tk = _get_token();
+
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ auto_size = true;
+ } else {
+ if (shader->structs.has(tk.text)) {
+ type = TYPE_STRUCT;
+ struct_name = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_tkpos(prev_pos);
+
+ pass_array = true;
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ pass_array = false;
+
+ if (!n) {
+ _set_error("Invalid data type for array");
+ return nullptr;
+ }
+
+ if (!_compare_datatypes(p_type, p_struct_name, p_array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
+ return nullptr;
+ }
+ return n;
+ }
+ type = get_token_datatype(tk.type);
+ }
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos = _get_tkpos();
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_CLOSE) {
array_size = p_array_size;
tk = _get_token();
} else {
@@ -3486,8 +3760,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_array_constructor(BlockNode *p_bloc
return nullptr;
}
- if (p_type != n->get_datatype() || p_struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'");
+ if (!_compare_datatypes(p_type, p_struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
return nullptr;
}
@@ -3587,50 +3860,73 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//make sure void is not used in expression
_set_error("Void value not allowed in Expression");
return nullptr;
- } else if (is_token_nonvoid_datatype(tk.type)) {
- //basic type constructor
+ } else if (is_token_nonvoid_datatype(tk.type) || tk.type == TK_CURLY_BRACKET_OPEN) {
+ if (tk.type == TK_CURLY_BRACKET_OPEN) {
+ //array constructor
- OperatorNode *func = alloc_node<OperatorNode>();
- func->op = OP_CONSTRUCT;
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ DataType datatype;
+ DataPrecision precision;
+ bool precision_defined = false;
- if (is_token_precision(tk.type)) {
- func->return_precision_cache = get_token_precision(tk.type);
+ if (is_token_precision(tk.type)) {
+ precision = get_token_precision(tk.type);
+ precision_defined = true;
+ tk = _get_token();
+ }
+
+ datatype = get_token_datatype(tk.type);
tk = _get_token();
- }
- VariableNode *funcname = alloc_node<VariableNode>();
- funcname->name = get_datatype_name(get_token_datatype(tk.type));
- func->arguments.push_back(funcname);
+ if (tk.type == TK_BRACKET_OPEN) {
+ //array constructor
- tk = _get_token();
- if (tk.type != TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after type name");
- return nullptr;
- }
+ _set_tkpos(prepos);
+ expr = _parse_array_constructor(p_block, p_function_info);
+ } else {
+ if (tk.type != TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after type name");
+ return nullptr;
+ }
+ //basic type constructor
- int carg = -1;
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op = OP_CONSTRUCT;
- bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+ if (precision_defined) {
+ func->return_precision_cache = precision;
+ }
- if (carg >= 0) {
- completion_type = COMPLETION_CALL_ARGUMENTS;
- completion_line = tk_line;
- completion_block = p_block;
- completion_function = funcname->name;
- completion_argument = carg;
- }
+ VariableNode *funcname = alloc_node<VariableNode>();
+ funcname->name = get_datatype_name(datatype);
+ func->arguments.push_back(funcname);
- if (!ok) {
- return nullptr;
- }
+ int carg = -1;
- if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
- _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
- return nullptr;
- }
+ bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+
+ if (carg >= 0) {
+ completion_type = COMPLETION_CALL_ARGUMENTS;
+ completion_line = tk_line;
+ completion_block = p_block;
+ completion_function = funcname->name;
+ completion_argument = carg;
+ }
- expr = _reduce_expression(p_block, func);
+ if (!ok) {
+ return nullptr;
+ }
+
+ if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) {
+ _set_error("No matching constructor found for: '" + String(funcname->name) + "'");
+ return nullptr;
+ }
+ expr = _reduce_expression(p_block, func);
+ }
+ }
} else if (tk.type == TK_IDENTIFIER) {
_set_tkpos(prepos);
@@ -3678,11 +3974,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!nexpr) {
return nullptr;
}
- Node *node = pstruct->members[i];
if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) {
- String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype());
- String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype());
- _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'");
return nullptr;
}
}
@@ -3704,7 +3996,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expr = func;
- } else { //a function
+ } else { //a function call
const StringName &name = identifier;
@@ -3716,7 +4008,9 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
int carg = -1;
+ pass_array = true;
bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg);
+ pass_array = false;
// Check if block has a variable with the same name as function to prevent shader crash.
ShaderLanguage::BlockNode *bnode = p_block;
@@ -3769,6 +4063,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
FunctionNode *call_function = shader->functions[function_index].function;
if (call_function) {
+ func->return_cache = call_function->get_datatype();
+ func->struct_name = call_function->get_datatype_name();
+ func->return_array_size = call_function->get_array_size();
+
//get current base function
FunctionNode *base_function = nullptr;
{
@@ -3943,60 +4241,61 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Node *assign_expression = nullptr;
if (array_size > 0) {
- tk = _get_token();
-
- if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
- _set_error("Expected '[','.' or '='");
- return nullptr;
- }
+ if (!pass_array) {
+ tk = _get_token();
- if (tk.type == TK_OP_ASSIGN) {
- if (is_const) {
- _set_error("Constants cannot be modified.");
+ if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD && tk.type != TK_OP_ASSIGN) {
+ _set_error("Expected '[','.' or '='");
return nullptr;
}
- assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
- if (!assign_expression) {
- return nullptr;
- }
- } else if (tk.type == TK_PERIOD) {
- completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
- call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
- if (!call_expression) {
- return nullptr;
- }
- data_type = call_expression->get_datatype();
- } else { // indexing
- index_expression = _parse_and_reduce_expression(p_block, p_function_info);
- if (!index_expression) {
- return nullptr;
- }
+ if (tk.type == TK_OP_ASSIGN) {
+ if (is_const) {
+ _set_error("Constants cannot be modified.");
+ return nullptr;
+ }
+ assign_expression = _parse_array_constructor(p_block, p_function_info, data_type, struct_name, array_size);
+ if (!assign_expression) {
+ return nullptr;
+ }
+ } else if (tk.type == TK_PERIOD) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ data_type = call_expression->get_datatype();
+ } else { // indexing
+ index_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!index_expression) {
+ return nullptr;
+ }
- if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
- _set_error("Only integer expressions are allowed for indexing");
- return nullptr;
- }
+ if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) {
+ _set_error("Only integer expressions are allowed for indexing");
+ return nullptr;
+ }
- if (index_expression->type == Node::TYPE_CONSTANT) {
- ConstantNode *cnode = (ConstantNode *)index_expression;
- if (cnode) {
- if (!cnode->values.is_empty()) {
- int value = cnode->values[0].sint;
- if (value < 0 || value >= array_size) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
- return nullptr;
+ if (index_expression->type == Node::TYPE_CONSTANT) {
+ ConstantNode *cnode = (ConstantNode *)index_expression;
+ if (cnode) {
+ if (!cnode->values.is_empty()) {
+ int value = cnode->values[0].sint;
+ if (value < 0 || value >= array_size) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1));
+ return nullptr;
+ }
}
}
}
- }
- tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return nullptr;
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return nullptr;
+ }
}
}
@@ -4008,6 +4307,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
arrname->call_expression = call_expression;
arrname->assign_expression = assign_expression;
arrname->is_const = is_const;
+ arrname->array_size = array_size;
expr = arrname;
} else {
VariableNode *varname = alloc_node<VariableNode>();
@@ -4072,6 +4372,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
DataType dt = expr->get_datatype();
String st = expr->get_datatype_name();
+ if (!expr->is_indexed() && expr->get_array_size() > 0) {
+ completion_class = TAG_ARRAY;
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (!call_expression) {
+ return nullptr;
+ }
+ expr = call_expression;
+ break;
+ }
+
StringName identifier;
if (_get_completable_identifier(p_block, dt == TYPE_STRUCT ? COMPLETION_STRUCT : COMPLETION_INDEX, identifier)) {
if (dt == TYPE_STRUCT) {
@@ -4348,6 +4660,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->has_swizzling_duplicates = repeated;
if (array_size > 0) {
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
if (tk.type == TK_OP_ASSIGN) {
if (last_type == IDENTIFIER_CONSTANT) {
@@ -4399,13 +4712,14 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
mn->index_expression = index_expression;
-
} else {
- _set_error("Expected '[','.' or '='");
- return nullptr;
+ if (!pass_array) {
+ _set_error("Expected '[','.' or '='");
+ return nullptr;
+ }
+ _set_tkpos(prev_pos);
}
}
-
expr = mn;
//todo
@@ -4430,117 +4744,130 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
DataType member_type = TYPE_VOID;
+ String member_struct_name;
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- case TYPE_VEC2:
- case TYPE_IVEC2:
- case TYPE_UVEC2:
- case TYPE_MAT2:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 2) {
- _set_error("Index out of range (0-1)");
- return nullptr;
+ if (expr->get_array_size() > 0) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= (uint32_t)expr->get_array_size()) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
+ return nullptr;
+ }
+ member_type = expr->get_datatype();
+ if (member_type == TYPE_STRUCT) {
+ member_struct_name = expr->get_datatype_name();
+ }
+ } else {
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ case TYPE_VEC2:
+ case TYPE_IVEC2:
+ case TYPE_UVEC2:
+ case TYPE_MAT2:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 2) {
+ _set_error("Index out of range (0-1)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC2:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC2:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC2:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC2:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT2:
- member_type = TYPE_VEC2;
- break;
- default:
- break;
- }
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC2:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC2:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC2:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC2:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT2:
+ member_type = TYPE_VEC2;
+ break;
+ default:
+ break;
+ }
- break;
- case TYPE_BVEC3:
- case TYPE_VEC3:
- case TYPE_IVEC3:
- case TYPE_UVEC3:
- case TYPE_MAT3:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 3) {
- _set_error("Index out of range (0-2)");
- return nullptr;
+ break;
+ case TYPE_BVEC3:
+ case TYPE_VEC3:
+ case TYPE_IVEC3:
+ case TYPE_UVEC3:
+ case TYPE_MAT3:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 3) {
+ _set_error("Index out of range (0-2)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC3:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC3:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC3:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC3:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT3:
- member_type = TYPE_VEC3;
- break;
- default:
- break;
- }
- break;
- case TYPE_BVEC4:
- case TYPE_VEC4:
- case TYPE_IVEC4:
- case TYPE_UVEC4:
- case TYPE_MAT4:
- if (index->type == Node::TYPE_CONSTANT) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= 4) {
- _set_error("Index out of range (0-3)");
- return nullptr;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC3:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC3:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC3:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC3:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT3:
+ member_type = TYPE_VEC3;
+ break;
+ default:
+ break;
+ }
+ break;
+ case TYPE_BVEC4:
+ case TYPE_VEC4:
+ case TYPE_IVEC4:
+ case TYPE_UVEC4:
+ case TYPE_MAT4:
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= 4) {
+ _set_error("Index out of range (0-3)");
+ return nullptr;
+ }
}
- }
- switch (expr->get_datatype()) {
- case TYPE_BVEC4:
- member_type = TYPE_BOOL;
- break;
- case TYPE_VEC4:
- member_type = TYPE_FLOAT;
- break;
- case TYPE_IVEC4:
- member_type = TYPE_INT;
- break;
- case TYPE_UVEC4:
- member_type = TYPE_UINT;
- break;
- case TYPE_MAT4:
- member_type = TYPE_VEC4;
- break;
- default:
- break;
+ switch (expr->get_datatype()) {
+ case TYPE_BVEC4:
+ member_type = TYPE_BOOL;
+ break;
+ case TYPE_VEC4:
+ member_type = TYPE_FLOAT;
+ break;
+ case TYPE_IVEC4:
+ member_type = TYPE_INT;
+ break;
+ case TYPE_UVEC4:
+ member_type = TYPE_UINT;
+ break;
+ case TYPE_MAT4:
+ member_type = TYPE_VEC4;
+ break;
+ default:
+ break;
+ }
+ break;
+ default: {
+ _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
+ return nullptr;
}
- break;
- default: {
- _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed");
- return nullptr;
}
}
-
OperatorNode *op = alloc_node<OperatorNode>();
op->op = OP_INDEX;
op->return_cache = member_type;
+ op->struct_name = member_struct_name;
op->arguments.push_back(expr);
op->arguments.push_back(index);
expr = op;
@@ -4556,7 +4883,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
op->arguments.push_back(expr);
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
_set_error("Invalid base type for increment/decrement operator");
return nullptr;
}
@@ -4874,13 +5201,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[i].is_op = false;
expression.write[i].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int j = 0; j < op->arguments.size(); j++) {
if (j > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[j]->get_datatype());
+ if (!op->arguments[j]->is_indexed() && op->arguments[j]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[j]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -4907,13 +5239,18 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.write[next_op - 1].is_op = false;
expression.write[next_op - 1].node = op;
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
at += " and ";
}
at += get_datatype_name(op->arguments[i]->get_datatype());
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid argument to ternary ?: operator: " + at);
return nullptr;
@@ -4960,7 +5297,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
//replace all 3 nodes by this operator and make it an expression
- if (!_validate_operator(op, &op->return_cache)) {
+ if (!_validate_operator(op, &op->return_cache, &op->return_array_size)) {
String at;
for (int i = 0; i < op->arguments.size(); i++) {
if (i > 0) {
@@ -4971,6 +5308,11 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else {
at += get_datatype_name(op->arguments[i]->get_datatype());
}
+ if (!op->arguments[i]->is_indexed() && op->arguments[i]->get_array_size() > 0) {
+ at += "[";
+ at += itos(op->arguments[i]->get_array_size());
+ at += "]";
+ }
}
_set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at);
return nullptr;
@@ -5227,6 +5569,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
ArrayDeclarationNode::Declaration decl;
decl.name = name;
decl.size = 0U;
+ decl.single_expression = false;
pos = _get_tkpos();
tk = _get_token();
@@ -5293,179 +5636,205 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
+ TkPos prev_pos = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_CURLY_BRACKET_OPEN) {
- if (unknown_size) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
-
- full_def = true;
+ if (tk.type == TK_IDENTIFIER) { // a function call array initialization
+ _set_tkpos(prev_pos);
+ pass_array = true;
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ pass_array = false;
- DataPrecision precision2 = PRECISION_DEFAULT;
- if (is_token_precision(tk.type)) {
- precision2 = get_token_precision(tk.type);
- tk = _get_token();
- if (shader->structs.has(tk.text)) {
- _set_error("Precision modifier cannot be used on structs.");
- return ERR_PARSE_ERROR;
+ if (!n) {
+ _set_error("Expected correct array initializer!");
+ return ERR_PARSE_ERROR;
+ } else {
+ if (unknown_size) {
+ decl.size = n->get_array_size();
+ var.array_size = n->get_array_size();
}
- if (!is_token_nonvoid_datatype(tk.type)) {
- _set_error("Expected datatype after precision");
+
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
- }
- DataType type2;
- StringName struct_name2 = "";
+ decl.single_expression = true;
+ decl.initializer.push_back(n);
+ }
- if (shader->structs.has(tk.text)) {
- type2 = TYPE_STRUCT;
- struct_name2 = tk.text;
- } else {
- if (!is_token_variable_datatype(tk.type)) {
- _set_error("Invalid data type for array");
+ tk = _get_token();
+ } else {
+ if (tk.type != TK_CURLY_BRACKET_OPEN) {
+ if (unknown_size) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
- type2 = get_token_datatype(tk.type);
- }
- int array_size2 = 0;
+ full_def = true;
- tk = _get_token();
- if (tk.type == TK_BRACKET_OPEN) {
- TkPos pos2 = _get_tkpos();
- tk = _get_token();
- if (tk.type == TK_BRACKET_CLOSE) {
- array_size2 = var.array_size;
+ DataPrecision precision2 = PRECISION_DEFAULT;
+ if (is_token_precision(tk.type)) {
+ precision2 = get_token_precision(tk.type);
tk = _get_token();
- } else {
- _set_tkpos(pos2);
-
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
- _set_error("Expected single integer constant > 0");
+ if (shader->structs.has(tk.text)) {
+ _set_error("Precision modifier cannot be used on structs.");
+ return ERR_PARSE_ERROR;
+ }
+ if (!is_token_nonvoid_datatype(tk.type)) {
+ _set_error("Expected datatype after precision");
return ERR_PARSE_ERROR;
}
+ }
- ConstantNode *cnode = (ConstantNode *)n;
- if (cnode->values.size() == 1) {
- array_size2 = cnode->values[0].sint;
- if (array_size2 <= 0) {
- _set_error("Expected single integer constant > 0");
- return ERR_PARSE_ERROR;
- }
- } else {
- _set_error("Expected single integer constant > 0");
+ DataType type2;
+ StringName struct_name2 = "";
+
+ if (shader->structs.has(tk.text)) {
+ type2 = TYPE_STRUCT;
+ struct_name2 = tk.text;
+ } else {
+ if (!is_token_variable_datatype(tk.type)) {
+ _set_error("Invalid data type for array");
return ERR_PARSE_ERROR;
}
+ type2 = get_token_datatype(tk.type);
+ }
+ int array_size2 = 0;
+
+ tk = _get_token();
+ if (tk.type == TK_BRACKET_OPEN) {
+ TkPos pos2 = _get_tkpos();
tk = _get_token();
- if (tk.type != TK_BRACKET_CLOSE) {
- _set_error("Expected ']'");
- return ERR_PARSE_ERROR;
+ if (tk.type == TK_BRACKET_CLOSE) {
+ array_size2 = var.array_size;
+ tk = _get_token();
} else {
+ _set_tkpos(pos2);
+
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ ConstantNode *cnode = (ConstantNode *)n;
+ if (cnode->values.size() == 1) {
+ array_size2 = cnode->values[0].sint;
+ if (array_size2 <= 0) {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error("Expected single integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ } else {
+ tk = _get_token();
+ }
}
- }
- } else {
- _set_error("Expected '['");
- return ERR_PARSE_ERROR;
- }
-
- if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
- String error_str = "Cannot convert from '";
- if (precision2 != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision2);
- error_str += " ";
- }
- if (type2 == TYPE_STRUCT) {
- error_str += struct_name2;
} else {
- error_str += get_datatype_name(type2);
- }
- error_str += "[";
- error_str += itos(array_size2);
- error_str += "]'";
- error_str += " to '";
- if (precision != PRECISION_DEFAULT) {
- error_str += get_precision_name(precision);
- error_str += " ";
+ _set_error("Expected '['");
+ return ERR_PARSE_ERROR;
}
- if (type == TYPE_STRUCT) {
- error_str += struct_name;
- } else {
- error_str += get_datatype_name(type);
+
+ if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) {
+ String error_str = "Cannot convert from '";
+ if (precision2 != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision2);
+ error_str += " ";
+ }
+ if (type2 == TYPE_STRUCT) {
+ error_str += struct_name2;
+ } else {
+ error_str += get_datatype_name(type2);
+ }
+ error_str += "[";
+ error_str += itos(array_size2);
+ error_str += "]'";
+ error_str += " to '";
+ if (precision != PRECISION_DEFAULT) {
+ error_str += get_precision_name(precision);
+ error_str += " ";
+ }
+ if (type == TYPE_STRUCT) {
+ error_str += struct_name;
+ } else {
+ error_str += get_datatype_name(type);
+ }
+ error_str += "[";
+ error_str += itos(var.array_size);
+ error_str += "]'";
+ _set_error(error_str);
+ return ERR_PARSE_ERROR;
}
- error_str += "[";
- error_str += itos(var.array_size);
- error_str += "]'";
- _set_error(error_str);
- return ERR_PARSE_ERROR;
}
- }
- bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
+ bool curly = tk.type == TK_CURLY_BRACKET_OPEN;
- if (unknown_size) {
- if (!curly) {
- _set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
- } else {
- if (full_def) {
- if (curly) {
- _set_error("Expected '('");
+ if (unknown_size) {
+ if (!curly) {
+ _set_error("Expected '{'");
return ERR_PARSE_ERROR;
}
+ } else {
+ if (full_def) {
+ if (curly) {
+ _set_error("Expected '('");
+ return ERR_PARSE_ERROR;
+ }
+ }
}
- }
- if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
- while (true) {
- Node *n = _parse_and_reduce_expression(p_block, p_function_info);
- if (!n) {
- return ERR_PARSE_ERROR;
- }
+ if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization
+ while (true) {
+ Node *n = _parse_and_reduce_expression(p_block, p_function_info);
+ if (!n) {
+ return ERR_PARSE_ERROR;
+ }
- if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
- _set_error("Expected constant expression");
- return ERR_PARSE_ERROR;
- }
+ if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) {
+ _set_error("Expected constant expression");
+ return ERR_PARSE_ERROR;
+ }
- if (var.type != n->get_datatype() || struct_name != n->get_datatype_name()) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? struct_name : get_datatype_name(var.type)) + "'");
- return ERR_PARSE_ERROR;
- }
+ if (!_compare_datatypes(var.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
+ return ERR_PARSE_ERROR;
+ }
- tk = _get_token();
- if (tk.type == TK_COMMA) {
- decl.initializer.push_back(n);
- continue;
- } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
- decl.initializer.push_back(n);
- break;
- } else {
- if (curly) {
- _set_error("Expected '}' or ','");
+ tk = _get_token();
+ if (tk.type == TK_COMMA) {
+ decl.initializer.push_back(n);
+ continue;
+ } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
+ } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) {
+ decl.initializer.push_back(n);
+ break;
} else {
- _set_error("Expected ')' or ','");
+ if (curly) {
+ _set_error("Expected '}' or ','");
+ } else {
+ _set_error("Expected ')' or ','");
+ }
+ return ERR_PARSE_ERROR;
}
+ }
+ if (unknown_size) {
+ decl.size = decl.initializer.size();
+ var.array_size = decl.initializer.size();
+ } else if (decl.initializer.size() != var.array_size) {
+ _set_error("Array size mismatch");
return ERR_PARSE_ERROR;
}
+ tk = _get_token();
}
- if (unknown_size) {
- decl.size = decl.initializer.size();
- var.array_size = decl.initializer.size();
- } else if (decl.initializer.size() != var.array_size) {
- _set_error("Array size mismatch");
- return ERR_PARSE_ERROR;
- }
- tk = _get_token();
}
} else {
if (unknown_size) {
@@ -5518,8 +5887,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
}
- if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'");
+ if (!_compare_datatypes(var.type, var.struct_name, var.array_size, n->get_datatype(), n->get_datatype_name(), n->get_array_size())) {
return ERR_PARSE_ERROR;
}
tk = _get_token();
@@ -5980,6 +6348,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
}
String return_struct_name = String(b->parent_function->return_struct_name);
+ String array_size_string;
+
+ if (b->parent_function->return_array_size > 0) {
+ array_size_string = "[" + itos(b->parent_function->return_array_size) + "]";
+ }
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
flow->flow_op = FLOW_OP_RETURN;
@@ -5989,18 +6362,27 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (tk.type == TK_SEMICOLON) {
//all is good
if (b->parent_function->return_type != TYPE_VOID) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
} else {
_set_tkpos(pos); //rollback, wants expression
+
+ pass_array = true;
Node *expr = _parse_and_reduce_expression(p_block, p_function_info);
if (!expr) {
return ERR_PARSE_ERROR;
}
+ pass_array = false;
+
+ bool array_size_incorrect = false;
+
+ if (b->parent_function->return_array_size > 0 && b->parent_function->return_array_size != expr->get_array_size()) {
+ array_size_incorrect = true;
+ }
- if (b->parent_function->return_type != expr->get_datatype() || return_struct_name != expr->get_datatype_name()) {
- _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + "'");
+ if (b->parent_function->return_type != expr->get_datatype() || array_size_incorrect || return_struct_name != expr->get_datatype_name()) {
+ _set_error("Expected return with an expression of type '" + (return_struct_name != "" ? return_struct_name : get_datatype_name(b->parent_function->return_type)) + array_size_string + "'");
return ERR_PARSE_ERROR;
}
@@ -6795,6 +7177,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
DataPrecision precision = PRECISION_DEFAULT;
DataType type;
StringName name;
+ int return_array_size = 0;
if (tk.type == TK_CONST) {
is_constant = true;
@@ -6832,10 +7215,33 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
}
TkPos prev_pos = _get_tkpos();
tk = _get_token();
+
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Cannot use arrays as return types");
- return ERR_PARSE_ERROR;
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ return_array_size = (int)tk.constant;
+ if (return_array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+
+ prev_pos = _get_tkpos();
}
+
_set_tkpos(prev_pos);
_get_completable_identifier(nullptr, COMPLETION_MAIN_FUNCTION, name);
@@ -7049,8 +7455,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
return ERR_PARSE_ERROR;
}
- if (constant.type != n->get_datatype() || n->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(constant.type)) + "'");
+ if (!_compare_datatypes(constant.type, struct_name, 0, n->get_datatype(), n->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
@@ -7111,8 +7516,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
constant.initializer = static_cast<ConstantNode *>(expr);
- if (type != expr->get_datatype() || expr->get_datatype_name() != struct_name) {
- _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(type)) + "'");
+ if (!_compare_datatypes(type, struct_name, 0, expr->get_datatype(), expr->get_datatype_name(), 0)) {
return ERR_PARSE_ERROR;
}
}
@@ -7192,6 +7596,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_struct_name = struct_name;
func_node->return_precision = precision;
+ func_node->return_array_size = return_array_size;
if (p_functions.has(name)) {
func_node->can_discard = p_functions[name].can_discard;
@@ -7245,6 +7650,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
StringName param_struct_name;
DataPrecision pprecision = PRECISION_DEFAULT;
bool use_precision = false;
+ int array_size = 0;
if (is_token_precision(tk.type)) {
pprecision = get_token_precision(tk.type);
@@ -7291,8 +7697,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
if (tk.type != TK_IDENTIFIER) {
_set_error("Expected identifier for argument name");
@@ -7326,14 +7753,41 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
arg.tex_argument_repeat = REPEAT_DEFAULT;
arg.is_const = is_const;
- func_node->arguments.push_back(arg);
-
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- _set_error("Arrays as parameters are not implemented yet");
- return ERR_PARSE_ERROR;
+ if (array_size > 0) {
+ _set_error("Array size is already defined!");
+ return ERR_PARSE_ERROR;
+ }
+ bool error = false;
+ tk = _get_token();
+
+ if (tk.type == TK_INT_CONSTANT) {
+ array_size = (int)tk.constant;
+
+ if (array_size > 0) {
+ tk = _get_token();
+ if (tk.type != TK_BRACKET_CLOSE) {
+ _set_error("Expected ']'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ error = true;
+ }
+ } else {
+ error = true;
+ }
+
+ if (error) {
+ _set_error("Expected integer constant > 0");
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
}
+ arg.array_size = array_size;
+ func_node->arguments.push_back(arg);
+
if (tk.type == TK_COMMA) {
tk = _get_token();
//do none and go on
@@ -7756,6 +8210,13 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
String calltip;
calltip += get_datatype_name(shader->functions[i].function->return_type);
+
+ if (shader->functions[i].function->return_array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->return_array_size);
+ calltip += "]";
+ }
+
calltip += " ";
calltip += shader->functions[i].name;
calltip += "(";
@@ -7787,6 +8248,12 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct
calltip += " ";
calltip += shader->functions[i].function->arguments[j].name;
+ if (shader->functions[i].function->arguments[j].array_size > 0) {
+ calltip += "[";
+ calltip += itos(shader->functions[i].function->arguments[j].array_size);
+ calltip += "]";
+ }
+
if (j == completion_argument) {
calltip += char32_t(0xFFFF);
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index c8c5bb1fa7..af66e32e06 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -369,6 +369,8 @@ public:
virtual DataType get_datatype() const { return TYPE_VOID; }
virtual String get_datatype_name() const { return ""; }
+ virtual int get_array_size() const { return 0; }
+ virtual bool is_indexed() const { return false; }
Node(Type t) :
type(t) {}
@@ -388,11 +390,15 @@ public:
struct OperatorNode : public Node {
DataType return_cache = TYPE_VOID;
DataPrecision return_precision_cache = PRECISION_DEFAULT;
+ int return_array_size = 0;
Operator op = OP_EQUAL;
StringName struct_name;
Vector<Node *> arguments;
- virtual DataType get_datatype() const { return return_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
+
+ virtual DataType get_datatype() const override { return return_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return return_array_size; }
+ virtual bool is_indexed() const override { return op == OP_INDEX; }
OperatorNode() :
Node(TYPE_OPERATOR) {}
@@ -402,10 +408,11 @@ public:
DataType datatype_cache = TYPE_VOID;
StringName name;
StringName struct_name;
- virtual DataType get_datatype() const { return datatype_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
bool is_const = false;
+ virtual DataType get_datatype() const override { return datatype_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+
VariableNode() :
Node(TYPE_VARIABLE) {}
};
@@ -420,9 +427,9 @@ public:
StringName name;
Node *initializer;
};
-
Vector<Declaration> declarations;
- virtual DataType get_datatype() const { return datatype; }
+
+ virtual DataType get_datatype() const override { return datatype; }
VariableDeclarationNode() :
Node(TYPE_VARIABLE_DECLARATION) {}
@@ -436,9 +443,12 @@ public:
Node *call_expression = nullptr;
Node *assign_expression = nullptr;
bool is_const = false;
+ int array_size = 0;
- virtual DataType get_datatype() const { return datatype_cache; }
- virtual String get_datatype_name() const { return String(struct_name); }
+ virtual DataType get_datatype() const override { return datatype_cache; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return array_size; }
+ virtual bool is_indexed() const override { return index_expression != nullptr; }
ArrayNode() :
Node(TYPE_ARRAY) {}
@@ -449,6 +459,10 @@ public:
String struct_name;
Vector<Node *> initializer;
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return struct_name; }
+ virtual int get_array_size() const override { return initializer.size(); }
+
ArrayConstructNode() :
Node(TYPE_ARRAY_CONSTRUCT) {}
};
@@ -464,10 +478,11 @@ public:
StringName name;
uint32_t size;
Vector<Node *> initializer;
+ bool single_expression;
};
-
Vector<Declaration> declarations;
- virtual DataType get_datatype() const { return datatype; }
+
+ virtual DataType get_datatype() const override { return datatype; }
ArrayDeclarationNode() :
Node(TYPE_ARRAY_DECLARATION) {}
@@ -487,8 +502,10 @@ public:
Vector<Value> values;
Vector<ArrayDeclarationNode::Declaration> array_declarations;
- virtual DataType get_datatype() const { return datatype; }
- virtual String get_datatype_name() const { return struct_name; }
+
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return struct_name; }
+ virtual int get_array_size() const override { return array_size; }
ConstantNode() :
Node(TYPE_CONSTANT) {}
@@ -553,8 +570,10 @@ public:
Node *call_expression = nullptr;
bool has_swizzling_duplicates = false;
- virtual DataType get_datatype() const { return datatype; }
- virtual String get_datatype_name() const { return String(struct_name); }
+ virtual DataType get_datatype() const override { return datatype; }
+ virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual int get_array_size() const override { return array_size; }
+ virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
MemberNode() :
Node(TYPE_MEMBER) {}
@@ -580,6 +599,7 @@ public:
bool tex_builtin_check;
StringName tex_builtin;
bool is_const;
+ int array_size;
Map<StringName, Set<int>> tex_argument_connect;
};
@@ -588,10 +608,15 @@ public:
DataType return_type = TYPE_VOID;
StringName return_struct_name;
DataPrecision return_precision = PRECISION_DEFAULT;
+ int return_array_size = 0;
Vector<Argument> arguments;
BlockNode *body = nullptr;
bool can_discard = false;
+ virtual DataType get_datatype() const override { return return_type; }
+ virtual String get_datatype_name() const override { return String(return_struct_name); }
+ virtual int get_array_size() const override { return return_array_size; }
+
FunctionNode() :
Node(TYPE_FUNCTION) {}
};
@@ -842,6 +867,8 @@ private:
int tk_line;
StringName current_function;
+ bool last_const = false;
+ bool pass_array = false;
StringName last_name;
VaryingFunctionNames varying_function_names;
@@ -894,7 +921,7 @@ private:
#endif // DEBUG_ENABLED
bool _is_operator_assign(Operator p_op) const;
bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr);
- bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr);
+ bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr, int *r_ret_size = nullptr);
struct BuiltinFuncDef {
enum { MAX_ARGS = 5 };
@@ -925,7 +952,8 @@ private:
static const BuiltinFuncOutArgs builtin_func_out_args[];
Error _validate_datatype(DataType p_type);
- bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
+ bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
+ bool _compare_datatypes_in_nodes(Node *a, Node *b);
bool _validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr);
@@ -936,6 +964,7 @@ private:
bool _check_node_constness(const Node *p_node) const;
Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info);
+ Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info);
Node *_parse_array_constructor(BlockNode *p_block, const FunctionInfo &p_function_info, DataType p_type, const StringName &p_struct_name, int p_array_size);
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);