summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt13
-rw-r--r--editor/action_map_editor.cpp1
-rw-r--r--editor/editor_about.cpp1
-rw-r--r--editor/editor_sectioned_inspector.cpp5
-rw-r--r--editor/editor_settings_dialog.cpp1
-rw-r--r--editor/editor_themes.cpp8
-rw-r--r--editor/import/dynamic_font_import_settings.cpp1
-rw-r--r--editor/import/scene_import_settings.cpp1
-rw-r--r--editor/plugins/script_text_editor.cpp15
-rw-r--r--editor/plugins/theme_editor_plugin.cpp10
-rw-r--r--editor/project_export.cpp1
-rw-r--r--editor/project_settings_editor.cpp1
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp14
-rw-r--r--modules/gdscript/gdscript_function.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp137
-rw-r--r--modules/gdscript/gdscript_parser.h6
-rw-r--r--modules/gdscript/gdscript_vm.cpp21
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd49
-rw-r--r--modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out19
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp1
-rw-r--r--platform/android/java/app/res/values/themes.xml4
-rw-r--r--scene/gui/tab_bar.cpp1
-rw-r--r--scene/gui/tree.cpp3
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp2
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_blur.glsl20
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/ssil_interleave.glsl20
32 files changed, 272 insertions, 98 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 18232b978e..06a5643dd3 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -118,6 +118,19 @@ Copyright: 2007, Starbreeze Studios
2014-2022, Godot Engine contributors.
License: Expat and Zlib
+Files: ./servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
+ ./servers/rendering/renderer_rd/shaders/ssao_blur.glsl
+ ./servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
+ ./servers/rendering/renderer_rd/shaders/ssao_interleave.glsl
+ ./servers/rendering/renderer_rd/shaders/ssao.glsl
+ ./servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+ ./servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+ ./servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+ ./servers/rendering/renderer_rd/shaders/ssil.glsl
+Comment: Intel ASSAO and related files
+Copyright: 2016, Intel Corporation
+License: Expat
+
Files: ./thirdparty/amd-fsr/
Comment: AMD FidelityFX Super Resolution
Copyright: 2021, Advanced Micro Devices, Inc.
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 6333b402da..698390a61e 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -644,6 +644,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
tab_container = memnew(TabContainer);
tab_container->set_use_hidden_tabs_for_min_size(true);
tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tab_container->set_theme_type_variation("TabContainerOdd");
tab_container->connect("tab_selected", callable_mp(this, &InputEventConfigurationDialog::_tab_selected));
main_vbox->add_child(tab_container);
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 88ad2633c0..6fafb2d91a 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -163,6 +163,7 @@ EditorAbout::EditorAbout() {
tc->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
tc->set_custom_minimum_size(Size2(400, 200) * EDSCALE);
tc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ tc->set_theme_type_variation("TabContainerOdd");
vbc->add_child(tc);
// Authors
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 801a1a4641..b7073665a8 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -250,6 +250,11 @@ void SectionedInspector::update_category_list() {
continue;
}
+ // Filter out unnecessary ProjectSettings sections, as they already have their dedicated tabs.
+ if (pi.name.begins_with("autoload") || pi.name.begins_with("editor_plugins") || pi.name.begins_with("shader_globals")) {
+ continue;
+ }
+
if (!filter.is_empty() && !_property_path_matches(pi.name, filter, name_style)) {
continue;
}
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index bec9f2dc51..3eb7d7ffbd 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -683,6 +683,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
undo_redo = memnew(UndoRedo);
tabs = memnew(TabContainer);
+ tabs->set_theme_type_variation("TabContainerOdd");
tabs->connect("tab_changed", callable_mp(this, &EditorSettingsDialog::_tabs_tab_changed));
add_child(tabs);
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 352cd453a7..c53c04af4e 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1152,14 +1152,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_content_panel->set_border_color(dark_color_2);
theme->set_stylebox("panel", "TabContainer", style_content_panel);
- // These styleboxes can be used on tabs against the base color background (e.g. nested tabs).
+ // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs).
+ theme->set_type_variation("TabContainerOdd", "TabContainer");
+
Ref<StyleBoxFlat> style_tab_selected_odd = style_tab_selected->duplicate();
style_tab_selected_odd->set_bg_color(disabled_bg_color);
- theme->set_stylebox("tab_selected_odd", "TabContainer", style_tab_selected_odd);
+ theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd);
Ref<StyleBoxFlat> style_content_panel_odd = style_content_panel->duplicate();
style_content_panel_odd->set_bg_color(disabled_bg_color);
- theme->set_stylebox("panel_odd", "TabContainer", style_content_panel_odd);
+ theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd);
// This stylebox is used in 3d and 2d viewports (no borders).
Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index e546f01205..97892e47d4 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -1418,6 +1418,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
main_pages->set_tab_alignment(TabBar::ALIGNMENT_CENTER);
main_pages->set_v_size_flags(Control::SIZE_EXPAND_FILL);
main_pages->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ main_pages->set_theme_type_variation("TabContainerOdd");
root_vb->add_child(main_pages);
label_warn = memnew(Label);
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 83dff30dfa..d9ff4f79de 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -1229,6 +1229,7 @@ SceneImportSettings::SceneImportSettings() {
data_mode = memnew(TabContainer);
tree_split->add_child(data_mode);
data_mode->set_custom_minimum_size(Size2(300 * EDSCALE, 0));
+ data_mode->set_theme_type_variation("TabContainerOdd");
property_split = memnew(HSplitContainer);
tree_split->add_child(property_split);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index b0cc0bff63..05c707c065 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1570,9 +1570,11 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
continue;
}
+ bool is_unique = false;
String path;
if (node->is_unique_name_in_owner()) {
- path = "%" + node->get_name();
+ path = node->get_name();
+ is_unique = true;
} else {
path = sn->get_path_to(node);
}
@@ -1585,9 +1587,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
String variable_name = String(node->get_name()).camelcase_to_underscore(true).validate_identifier();
if (use_type) {
- text_to_drop += vformat("@onready var %s: %s = $%s\n", variable_name, node->get_class_name(), path);
+ text_to_drop += vformat("@onready var %s: %s = %s%s\n", variable_name, node->get_class_name(), is_unique ? "%" : "$", path);
} else {
- text_to_drop += vformat("@onready var %s = $%s\n", variable_name, path);
+ text_to_drop += vformat("@onready var %s = %s%s\n", variable_name, is_unique ? "%" : "$", path);
}
}
} else {
@@ -1602,19 +1604,22 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data
continue;
}
+ bool is_unique = false;
String path;
if (node->is_unique_name_in_owner()) {
- path = "%" + node->get_name();
+ path = node->get_name();
+ is_unique = true;
} else {
path = sn->get_path_to(node);
}
+
for (const String &segment : path.split("/")) {
if (!segment.is_valid_identifier()) {
path = path.c_escape().quote(quote_style);
break;
}
}
- text_to_drop += "$" + path;
+ text_to_drop += (is_unique ? "%" : "$") + path;
}
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 400611c0e6..418115c041 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -1868,9 +1868,6 @@ void ThemeItemEditorDialog::_notification(int p_what) {
edit_items_remove_all->set_icon(get_theme_icon(SNAME("ThemeRemoveAllItems"), SNAME("EditorIcons")));
import_another_theme_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
-
- tc->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("tab_selected_odd"), SNAME("TabContainer")));
- tc->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
} break;
}
}
@@ -1893,6 +1890,7 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito
tc = memnew(TabContainer);
add_child(tc);
+ tc->set_theme_type_variation("TabContainerOdd");
// Edit Items tab.
HSplitContainer *edit_dialog_hs = memnew(HSplitContainer);
@@ -3302,9 +3300,6 @@ void ThemeTypeEditor::_notification(int p_what) {
data_type_tabs->set_tab_icon(5, get_theme_icon(SNAME("StyleBoxFlat"), SNAME("EditorIcons")));
data_type_tabs->set_tab_icon(6, get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
- data_type_tabs->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("tab_selected_odd"), SNAME("TabContainer")));
- data_type_tabs->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
-
type_variation_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
@@ -3404,6 +3399,7 @@ ThemeTypeEditor::ThemeTypeEditor() {
main_vb->add_child(data_type_tabs);
data_type_tabs->set_v_size_flags(SIZE_EXPAND_FILL);
data_type_tabs->set_use_hidden_tabs_for_min_size(true);
+ data_type_tabs->set_theme_type_variation("TabContainerOdd");
color_items_list = _create_item_list(Theme::DATA_TYPE_COLOR);
constant_items_list = _create_item_list(Theme::DATA_TYPE_CONSTANT);
@@ -3586,7 +3582,7 @@ void ThemeEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
preview_tabs->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("ThemeEditorPreviewFG"), SNAME("EditorStyles")));
preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox(SNAME("ThemeEditorPreviewBG"), SNAME("EditorStyles")));
- preview_tabs_content->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel_odd"), SNAME("TabContainer")));
+ preview_tabs_content->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainerOdd")));
add_preview_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 503eb5000b..70627d5e82 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -1064,6 +1064,7 @@ ProjectExportDialog::ProjectExportDialog() {
sections = memnew(TabContainer);
sections->set_use_hidden_tabs_for_min_size(true);
+ sections->set_theme_type_variation("TabContainerOdd");
settings_vb->add_child(sections);
sections->set_v_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 58f69436a5..404199d2da 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -560,6 +560,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
tab_container = memnew(TabContainer);
tab_container->set_use_hidden_tabs_for_min_size(true);
+ tab_container->set_theme_type_variation("TabContainerOdd");
add_child(tab_container);
VBoxContainer *general_editor = memnew(VBoxContainer);
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 191568661d..b86e9b386d 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -387,9 +387,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
in_member_variable = false;
}
- if (!in_node_path && in_region == -1 && str[j] == '$') {
+ if (!in_node_path && in_region == -1 && (str[j] == '$' || str[j] == '%')) {
in_node_path = true;
- } else if (in_region != -1 || (is_a_symbol && str[j] != '/')) {
+ } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) {
in_node_path = false;
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 478fafc930..910f94a936 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -667,20 +667,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
case GDScriptParser::Node::GET_NODE: {
const GDScriptParser::GetNodeNode *get_node = static_cast<const GDScriptParser::GetNodeNode *>(p_expression);
- String node_name;
- if (get_node->string != nullptr) {
- node_name += String(get_node->string->value);
- } else {
- for (int i = 0; i < get_node->chain.size(); i++) {
- if (i > 0) {
- node_name += "/";
- }
- node_name += get_node->chain[i]->name;
- }
- }
-
Vector<GDScriptCodeGenerator::Address> args;
- args.push_back(codegen.add_constant(NodePath(node_name)));
+ args.push_back(codegen.add_constant(NodePath(get_node->full_path)));
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index deef593f34..cd3b7d69c5 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -270,6 +270,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->exit_function();
}
+
+ _clear_stack();
#endif
}
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 716fcb8a7e..bc225850c9 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2830,51 +2830,97 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p_previous_operand, bool p_can_assign) {
- if (match(GDScriptTokenizer::Token::LITERAL)) {
- if (previous.literal.get_type() != Variant::STRING) {
- push_error(R"(Expect node path as string or identifier after "$".)");
+ if (!current.is_node_name() && !check(GDScriptTokenizer::Token::LITERAL) && !check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous.get_name()));
+ return nullptr;
+ }
+
+ if (check(GDScriptTokenizer::Token::LITERAL)) {
+ if (current.literal.get_type() != Variant::STRING) {
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous.get_name()));
return nullptr;
}
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- make_completion_context(COMPLETION_GET_NODE, get_node);
- get_node->string = parse_literal();
- return get_node;
- } else if (current.is_node_name()) {
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- int chain_position = 0;
- do {
- make_completion_context(COMPLETION_GET_NODE, get_node, chain_position++);
- if (!current.is_node_name()) {
- push_error(R"(Expect node path after "/".)");
+ }
+
+ GetNodeNode *get_node = alloc_node<GetNodeNode>();
+
+ // Store the last item in the path so the parser knows what to expect.
+ // Allow allows more specific error messages.
+ enum PathState {
+ PATH_STATE_START,
+ PATH_STATE_SLASH,
+ PATH_STATE_PERCENT,
+ PATH_STATE_NODE_NAME,
+ } path_state = PATH_STATE_START;
+
+ if (previous.type == GDScriptTokenizer::Token::DOLLAR) {
+ // Detect initial slash, which will be handled in the loop if it matches.
+ match(GDScriptTokenizer::Token::SLASH);
+#ifdef DEBUG_ENABLED
+ } else {
+ get_node->use_dollar = false;
+#endif
+ }
+
+ int context_argument = 0;
+
+ do {
+ if (previous.type == GDScriptTokenizer::Token::PERCENT) {
+ if (path_state != PATH_STATE_START && path_state != PATH_STATE_SLASH) {
+ push_error(R"("%" is only valid in the beginning of a node name (either after "$" or after "/"))");
return nullptr;
}
- advance();
- IdentifierNode *identifier = alloc_node<IdentifierNode>();
- identifier->name = previous.get_identifier();
- get_node->chain.push_back(identifier);
- } while (match(GDScriptTokenizer::Token::SLASH));
- return get_node;
- } else if (match(GDScriptTokenizer::Token::SLASH)) {
- GetNodeNode *get_node = alloc_node<GetNodeNode>();
- IdentifierNode *identifier_root = alloc_node<IdentifierNode>();
- get_node->chain.push_back(identifier_root);
- int chain_position = 0;
- do {
- make_completion_context(COMPLETION_GET_NODE, get_node, chain_position++);
- if (!current.is_node_name()) {
- push_error(R"(Expect node path after "/".)");
+ get_node->full_path += "%";
+
+ path_state = PATH_STATE_PERCENT;
+ } else if (previous.type == GDScriptTokenizer::Token::SLASH) {
+ if (path_state != PATH_STATE_START && path_state != PATH_STATE_NODE_NAME) {
+ push_error(R"("/" is only valid at the beginning of the path or after a node name.)");
return nullptr;
}
+
+ get_node->full_path += "/";
+
+ path_state = PATH_STATE_SLASH;
+ }
+
+ make_completion_context(COMPLETION_GET_NODE, get_node, context_argument++);
+
+ if (match(GDScriptTokenizer::Token::LITERAL)) {
+ if (previous.literal.get_type() != Variant::STRING) {
+ String previous_token;
+ switch (path_state) {
+ case PATH_STATE_START:
+ previous_token = "$";
+ break;
+ case PATH_STATE_PERCENT:
+ previous_token = "%";
+ break;
+ case PATH_STATE_SLASH:
+ previous_token = "/";
+ break;
+ default:
+ break;
+ }
+ push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous_token));
+ return nullptr;
+ }
+
+ get_node->full_path += previous.literal.operator String();
+
+ path_state = PATH_STATE_NODE_NAME;
+ } else if (current.is_node_name()) {
advance();
- IdentifierNode *identifier = alloc_node<IdentifierNode>();
- identifier->name = previous.get_identifier();
- get_node->chain.push_back(identifier);
- } while (match(GDScriptTokenizer::Token::SLASH));
- return get_node;
- } else {
- push_error(R"(Expect node path as string or identifier after "$".)");
- return nullptr;
- }
+ get_node->full_path += previous.get_identifier();
+
+ path_state = PATH_STATE_NODE_NAME;
+ } else if (!check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) {
+ push_error(vformat(R"(Unexpected "%s" in node path.)", current.get_name()));
+ return nullptr;
+ }
+ } while (match(GDScriptTokenizer::Token::SLASH) || match(GDScriptTokenizer::Token::PERCENT));
+
+ return get_node;
}
GDScriptParser::ExpressionNode *GDScriptParser::parse_preload(ExpressionNode *p_previous_operand, bool p_can_assign) {
@@ -3278,7 +3324,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // STAR,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_POWER }, // STAR_STAR,
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // SLASH,
- { nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT,
+ { &GDScriptParser::parse_get_node, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT,
// Assignment
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // EQUAL,
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PLUS_EQUAL,
@@ -4258,17 +4304,10 @@ void GDScriptParser::TreePrinter::print_function(FunctionNode *p_function, const
}
void GDScriptParser::TreePrinter::print_get_node(GetNodeNode *p_get_node) {
- push_text("$");
- if (p_get_node->string != nullptr) {
- print_literal(p_get_node->string);
- } else {
- for (int i = 0; i < p_get_node->chain.size(); i++) {
- if (i > 0) {
- push_text("/");
- }
- print_identifier(p_get_node->chain[i]);
- }
+ if (p_get_node->use_dollar) {
+ push_text("$");
}
+ push_text(p_get_node->full_path);
}
void GDScriptParser::TreePrinter::print_identifier(IdentifierNode *p_identifier) {
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 96b9a10d3c..e3f8d4b8ba 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -749,8 +749,10 @@ public:
};
struct GetNodeNode : public ExpressionNode {
- LiteralNode *string = nullptr;
- Vector<IdentifierNode *> chain;
+ String full_path;
+#ifdef DEBUG_ENABLED
+ bool use_dollar = true;
+#endif
GetNodeNode() {
type = GET_NODE;
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 8f85d8159b..55f4ebb1c5 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -3450,23 +3450,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
}
- // Check if this function has been interrupted by `await`.
- // If that is the case we want to keep it in the debugger until it actually exits.
+ // Check if this is not the last time it was interrupted by `await` or if it's the first time executing.
+ // If that is the case then we exit the function as normal. Otherwise we postpone it until the last `await` is completed.
// This ensures the call stack can be properly shown when using `await`, showing what resumed the function.
- if (!awaited) {
+ if (!p_state || awaited) {
if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->exit_function();
}
- }
#endif
- // Clear the stack even if there was an `await`.
- // The stack saved in the state is a copy, so this needs to be destructed to avoid leaks.
- if (_stack_size) {
- // Free stack.
- for (int i = 0; i < _stack_size; i++) {
+ // Free stack, except reserved addresses.
+ for (int i = 3; i < _stack_size; i++) {
stack[i].~Variant();
}
+#ifdef DEBUG_ENABLED
+ }
+#endif
+
+ // Always free reserved addresses, since they are never copied.
+ for (int i = 0; i < 3; i++) {
+ stack[i].~Variant();
}
return retvalue;
diff --git a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
+++ b/modules/gdscript/tests/scripts/parser/errors/dollar-assignment-bug-53696.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
+++ b/modules/gdscript/tests/scripts/parser/errors/nothing_after_dollar.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
index b3dc181a22..9fafcb5a64 100644
--- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
+++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path as string or identifier after "$".
+Expected node path as string or identifier after "$".
diff --git a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
index dcb4ccecb0..3062f0be70 100644
--- a/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
+++ b/modules/gdscript/tests/scripts/parser/errors/wrong_value_after_dollar_slash.out
@@ -1,2 +1,2 @@
GDTEST_PARSER_ERROR
-Expect node path after "/".
+Expected node path as string or identifier after "/".
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
new file mode 100644
index 0000000000..f04f4de08d
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.gd
@@ -0,0 +1,49 @@
+extends Node
+
+func test():
+ var child = Node.new()
+ child.name = "Child"
+ add_child(child)
+ child.owner = self
+
+ var hey = Node.new()
+ hey.name = "Hey"
+ child.add_child(hey)
+ hey.owner = self
+ hey.unique_name_in_owner = true
+
+ var fake_hey = Node.new()
+ fake_hey.name = "Hey"
+ add_child(fake_hey)
+ fake_hey.owner = self
+
+ var sub_child = Node.new()
+ sub_child.name = "SubChild"
+ hey.add_child(sub_child)
+ sub_child.owner = self
+
+ var howdy = Node.new()
+ howdy.name = "Howdy"
+ sub_child.add_child(howdy)
+ howdy.owner = self
+ howdy.unique_name_in_owner = true
+
+ print(hey == $Child/Hey)
+ print(howdy == $Child/Hey/SubChild/Howdy)
+
+ print(%Hey == hey)
+ print($%Hey == hey)
+ print(%"Hey" == hey)
+ print($"%Hey" == hey)
+ print($%"Hey" == hey)
+ print(%Hey/%Howdy == howdy)
+ print($%Hey/%Howdy == howdy)
+ print($"%Hey/%Howdy" == howdy)
+ print($"%Hey"/"%Howdy" == howdy)
+ print(%"Hey"/"%Howdy" == howdy)
+ print($%"Hey"/"%Howdy" == howdy)
+ print($"%Hey"/%"Howdy" == howdy)
+ print(%"Hey"/%"Howdy" == howdy)
+ print($%"Hey"/%"Howdy" == howdy)
+ print(%"Hey/%Howdy" == howdy)
+ print($%"Hey/%Howdy" == howdy)
diff --git a/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out
new file mode 100644
index 0000000000..041c4439b0
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/dollar_and_percent_get_node.out
@@ -0,0 +1,19 @@
+GDTEST_OK
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
+true
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index 6e9a2e1b61..87b7f50224 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -344,6 +344,7 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() {
tabs = memnew(TabContainer);
tabs->set_h_size_flags(SIZE_EXPAND_FILL);
tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ tabs->set_theme_type_variation("TabContainerOdd");
tabs->connect("tab_changed", callable_mp(this, &OpenXRActionMapEditor::_on_tabs_tab_changed));
tabs->connect("tab_button_pressed", callable_mp(this, &OpenXRActionMapEditor::_on_tab_button_pressed));
add_child(tabs);
diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml
index 99f723f5ba..d64b50ca45 100644
--- a/platform/android/java/app/res/values/themes.xml
+++ b/platform/android/java/app/res/values/themes.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen"/>
+ <style name="GodotAppMainTheme" parent="@android:style/Theme.Black.NoTitleBar"/>
- <style name="GodotAppSplashTheme" parent="@style/GodotAppMainTheme">
+ <style name="GodotAppSplashTheme" parent="@android:style/Theme.Black.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@drawable/splash_drawable</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index b96ba0ebf9..fec8d11bef 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -862,6 +862,7 @@ void TabBar::_update_hover() {
void TabBar::_update_cache() {
if (tabs.is_empty()) {
+ buttons_visible = false;
return;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index b4602e7a5a..d3e7540790 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -2169,7 +2169,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int parent_ofs = p_pos.x + cache.item_margin;
Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
- if (c->get_first_child() != nullptr) {
+ if (c->get_visible_child_count() > 0) {
root_pos -= Point2i(cache.arrow->get_width(), 0);
}
@@ -4523,6 +4523,7 @@ Point2 Tree::get_scroll() const {
}
void Tree::scroll_to_item(TreeItem *p_item, bool p_center_on_item) {
+ ERR_FAIL_NULL(p_item);
if (!is_visible_in_tree() || !p_item->is_visible()) {
return; // Hack to work around crash in get_item_rect() if Tree is not in tree.
}
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index bed9b02da1..b735283ebe 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -1671,7 +1671,7 @@ void GodotPhysicsServer3D::flush_queries() {
values.push_back("flush_queries");
values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg));
- values.push_front("physics");
+ values.push_front("physics_3d");
EngineDebugger::profiler_add_frame_data("servers", values);
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
index ee21d46a74..47c56571f6 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
@@ -1,3 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2016, Intel Corporation
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of
+// the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File changes (yyyy-mm-dd)
+// 2016-09-07: filip.strugar@intel.com: first commit
+// 2020-12-05: clayjohn: convert to Vulkan and Godot
+// 2021-05-27: clayjohn: convert SSAO to SSIL
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
#[compute]
#version 450
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
index 8818f8cada..6b6b02739d 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
@@ -15,6 +15,7 @@
// File changes (yyyy-mm-dd)
// 2016-09-07: filip.strugar@intel.com: first commit
// 2020-12-05: clayjohn: convert to Vulkan and Godot
+// 2021-05-27: clayjohn: convert SSAO to SSIL
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[compute]
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
index fa4309353d..9e86ac0cf0 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
@@ -1,3 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2016, Intel Corporation
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of
+// the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// File changes (yyyy-mm-dd)
+// 2016-09-07: filip.strugar@intel.com: first commit
+// 2020-12-05: clayjohn: convert to Vulkan and Godot
+// 2021-05-27: clayjohn: convert SSAO to SSIL
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
#[compute]
#version 450