summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/web_builds.yml2
-rw-r--r--COPYRIGHT.txt42
-rw-r--r--core/variant/variant_construct.h8
-rw-r--r--doc/classes/Array.xml2
-rw-r--r--doc/classes/EditorSettings.xml4
-rw-r--r--doc/classes/InputEventShortcut.xml2
-rw-r--r--doc/classes/SceneTree.xml2
-rw-r--r--editor/animation_track_editor.cpp41
-rw-r--r--editor/editor_node.cpp3
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--main/main.cpp10
-rw-r--r--modules/gdscript/gdscript_compiler.cpp18
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out6
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd20
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out1
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd11
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out1
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp26
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs2
-rw-r--r--platform/android/export/export_plugin.cpp3
-rw-r--r--platform/android/java/build.gradle2
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp7
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h2
-rw-r--r--platform/macos/display_server_macos.h2
-rw-r--r--platform/macos/display_server_macos.mm8
-rw-r--r--platform/web/detect.py5
-rw-r--r--platform/web/js/libs/library_godot_audio.js21
-rw-r--r--platform/windows/detect.py4
-rw-r--r--platform/windows/display_server_windows.cpp28
-rw-r--r--platform/windows/display_server_windows.h4
-rw-r--r--platform/windows/gl_manager_windows_native.cpp4
-rw-r--r--scene/animation/animation_blend_tree.cpp9
-rw-r--r--scene/animation/animation_node_state_machine.cpp7
-rw-r--r--scene/animation/animation_node_state_machine.h2
-rw-r--r--scene/animation/animation_tree.cpp6
-rw-r--r--scene/animation/animation_tree.h4
-rw-r--r--scene/gui/text_edit.cpp4
-rw-r--r--scene/main/window.cpp12
-rw-r--r--servers/audio_server.h2
-rw-r--r--servers/display_server.cpp2
-rw-r--r--servers/display_server.h2
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/rendering/shader_compiler.cpp7
-rw-r--r--servers/rendering/shader_language.cpp19
-rw-r--r--servers/rendering/shader_language.h75
-rw-r--r--tests/scene/test_graph_node.h4
50 files changed, 271 insertions, 196 deletions
diff --git a/.github/workflows/web_builds.yml b/.github/workflows/web_builds.yml
index de8339bf1b..add5fa8154 100644
--- a/.github/workflows/web_builds.yml
+++ b/.github/workflows/web_builds.yml
@@ -6,7 +6,7 @@ on:
env:
# Used for the cache key. Add version suffix to force clean build.
GODOT_BASE_BRANCH: master
- SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no
+ SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes
EM_VERSION: 3.1.59
EM_CACHE_FOLDER: "emsdk-cache"
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 04c81b9ddf..1e32c87c01 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -581,48 +581,6 @@ License: Apache-2.0
See the License for the specific language governing permissions and
limitations under the License.
-License: Bitstream Vera Fonts Copyright
- Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a
- trademark of Bitstream, Inc.
- .
- Permission is hereby granted, free of charge, to any person obtaining a copy of
- the fonts accompanying this license ("Fonts") and associated documentation
- files (the "Font Software"), to reproduce and distribute the Font Software,
- including without limitation the rights to use, copy, merge, publish,
- distribute, and/or sell copies of the Font Software, and to permit persons to
- whom the Font Software is furnished to do so, subject to the following
- conditions:
- .
- The above copyright and trademark notices and this permission notice shall be
- included in all copies of one or more of the Font Software typefaces.
- .
- The Font Software may be modified, altered, or added to, and in particular the
- designs of glyphs or characters in the Fonts may be modified and additional
- glyphs or characters may be added to the Fonts, only if the fonts are renamed
- to names not containing either the words "Bitstream" or the word "Vera".
- .
- This License becomes null and void to the extent applicable to Fonts or Font
- Software that has been modified and is distributed under the "Bitstream Vera"
- names.
- .
- The Font Software may be sold as part of a larger software package but no copy
- of one or more of the Font Software typefaces may be sold by itself.
- .
- THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
- TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL,
- SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO
- USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
- .
- Except as contained in this notice, the names of GNOME, the GNOME Foundation,
- and Bitstream Inc., shall not be used in advertising or otherwise to promote
- the sale, use or other dealings in this Font Software without prior written
- authorization from the GNOME Foundation or Bitstream Inc., respectively. For
- further information, contact: fonts at gnome dot org.
-
License: BSD-2-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
diff --git a/core/variant/variant_construct.h b/core/variant/variant_construct.h
index b824044b82..5afdb884f6 100644
--- a/core/variant/variant_construct.h
+++ b/core/variant/variant_construct.h
@@ -153,11 +153,14 @@ public:
class VariantConstructorObject {
public:
static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
- VariantInternal::clear(&r_ret);
if (p_args[0]->get_type() == Variant::NIL) {
+ VariantInternal::clear(&r_ret);
+ VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
r_error.error = Callable::CallError::CALL_OK;
} else if (p_args[0]->get_type() == Variant::OBJECT) {
+ VariantInternal::clear(&r_ret);
+ VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign(&r_ret, p_args[0]);
r_error.error = Callable::CallError::CALL_OK;
} else {
@@ -169,6 +172,7 @@ public:
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
+ VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign(r_ret, p_args[0]);
}
static void ptr_construct(void *base, const void **p_args) {
@@ -198,11 +202,13 @@ public:
}
VariantInternal::clear(&r_ret);
+ VariantTypeChanger<Object *>::change(&r_ret);
VariantInternal::object_assign_null(&r_ret);
}
static inline void validated_construct(Variant *r_ret, const Variant **p_args) {
VariantInternal::clear(r_ret);
+ VariantTypeChanger<Object *>::change(r_ret);
VariantInternal::object_assign_null(r_ret);
}
static void ptr_construct(void *base, const void **p_args) {
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 3731b8dcf1..bd0e05f8e0 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -694,7 +694,7 @@
<method name="sort">
<return type="void" />
<description>
- Sorts the array in ascending order. The final order is dependent on the "less than" ([code]&gt;[/code]) comparison between elements.
+ Sorts the array in ascending order. The final order is dependent on the "less than" ([code]&lt;[/code]) comparison between elements.
[codeblocks]
[gdscript]
var numbers = [10, 5, 2.5, 8]
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index b66e5bc091..d63c71a351 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -1074,7 +1074,7 @@
If [code]true[/code], allows scrolling past the end of the file.
</member>
<member name="text_editor/behavior/navigation/smooth_scrolling" type="bool" setter="" getter="">
- If [code]true[/code], allows scrolling in sub-line intervals and enables a smooth scrolling animation when using the mouse wheel to scroll.
+ If [code]true[/code], enables a smooth scrolling animation when using the mouse wheel to scroll. See [member text_editor/behavior/navigation/v_scroll_speed] for the speed of this animation.
[b]Note:[/b] [member text_editor/behavior/navigation/smooth_scrolling] currently behaves poorly in projects where [member ProjectSettings.physics/common/physics_ticks_per_second] has been increased significantly from its default value ([code]60[/code]). In this case, it is recommended to disable this setting.
</member>
<member name="text_editor/behavior/navigation/stay_in_script_editor_on_node_selected" type="bool" setter="" getter="">
@@ -1087,7 +1087,7 @@
If [code]true[/code], uses the characters in [code]`!"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^`{|}~[/code], the Unicode General Punctuation table, and the Unicode CJK Punctuation table as word separators for word navigation and operations. If [code]false[/code], a subset of these characters are used and does not include the characters [code]&lt;&gt;$~^=+|[/code]. This is in addition to custom characters if [member text_editor/behavior/navigation/use_custom_word_separators] is also enabled. These characters are used to determine where a word stops. Word navigation and operations include double-clicking on a word or holding [kbd]Ctrl[/kbd] ([kbd]Cmd[/kbd] on macOS) while pressing [kbd]left[/kbd], [kbd]right[/kbd], [kbd]backspace[/kbd], or [kbd]delete[/kbd].
</member>
<member name="text_editor/behavior/navigation/v_scroll_speed" type="int" setter="" getter="">
- The number of pixels to scroll with every mouse wheel increment. Higher values make the script scroll by faster when using the mouse wheel.
+ The speed of scrolling in lines per second when [member text_editor/behavior/navigation/smooth_scrolling] is [code]true[/code]. Higher values make the script scroll by faster when using the mouse wheel.
[b]Note:[/b] You can hold down [kbd]Alt[/kbd] while using the mouse wheel to temporarily scroll 5 times faster.
</member>
<member name="text_editor/completion/add_node_path_literals" type="bool" setter="" getter="">
diff --git a/doc/classes/InputEventShortcut.xml b/doc/classes/InputEventShortcut.xml
index 3c698fd4fb..414dd7e8ce 100644
--- a/doc/classes/InputEventShortcut.xml
+++ b/doc/classes/InputEventShortcut.xml
@@ -4,7 +4,7 @@
Represents a triggered keyboard [Shortcut].
</brief_description>
<description>
- InputEventShortcut is a special event that can be received in [method Node._unhandled_key_input]. It is typically sent by the editor's Command Palette to trigger actions, but can also be sent manually using [method Viewport.push_input].
+ InputEventShortcut is a special event that can be received in [method Node._input], [method Node._shortcut_input], and [method Node._unhandled_input]. It is typically sent by the editor's Command Palette to trigger actions, but can also be sent manually using [method Viewport.push_input].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index bae5fe1205..77baef9d08 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -156,7 +156,7 @@
<param index="0" name="group" type="StringName" />
<param index="1" name="notification" type="int" />
<description>
- Calls [method Object.notification] with the given [param notification] to all nodes inside this tree added to the [param group]. See also [method call_group] and [method set_group].
+ Calls [method Object.notification] with the given [param notification] to all nodes inside this tree added to the [param group]. See also [url=$DOCS_URL/tutorials/best_practices/godot_notifications.html]Godot notifications[/url] and [method call_group] and [method set_group].
[b]Note:[/b] This method acts immediately on all selected nodes at once, which may cause stuttering in some performance-intensive situations.
</description>
</method>
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index b6636ca576..14188a42a0 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -43,6 +43,7 @@
#include "editor/inspector_dock.h"
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/themes/editor_scale.h"
+#include "scene/3d/mesh_instance_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/animation/tween.h"
#include "scene/gui/check_box.h"
@@ -5120,16 +5121,7 @@ void AnimationTrackEditor::_new_track_property_selected(const String &p_name) {
Animation::InterpolationType interp_type = Animation::INTERPOLATION_LINEAR;
bool loop_wrap = true;
_fetch_value_track_options(full_path, &update_mode, &interp_type, &loop_wrap);
- if (adding_track_type == Animation::TYPE_VALUE) {
- undo_redo->create_action(TTR("Add Track"));
- undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
- undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), full_path);
- undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", animation->get_track_count(), interp_type);
- undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", animation->get_track_count(), loop_wrap);
- undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", animation->get_track_count(), update_mode);
- undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count());
- undo_redo->commit_action();
- } else {
+ if (adding_track_type == Animation::TYPE_BEZIER) {
Vector<String> subindices;
{
// Hack.
@@ -5157,6 +5149,24 @@ void AnimationTrackEditor::_new_track_property_selected(const String &p_name) {
undo_redo->add_undo_method(animation.ptr(), "remove_track", base_track);
}
undo_redo->commit_action();
+ } else {
+ bool is_blend_shape = adding_track_type == Animation::TYPE_BLEND_SHAPE;
+ if (is_blend_shape) {
+ PackedStringArray split = p_name.split("/");
+ if (!split.is_empty()) {
+ full_path = String(adding_track_path) + ":" + split[split.size() - 1];
+ }
+ }
+ undo_redo->create_action(TTR("Add Track"));
+ undo_redo->add_do_method(animation.ptr(), "add_track", adding_track_type);
+ undo_redo->add_do_method(animation.ptr(), "track_set_path", animation->get_track_count(), full_path);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", animation->get_track_count(), interp_type);
+ undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_loop_wrap", animation->get_track_count(), loop_wrap);
+ if (!is_blend_shape) {
+ undo_redo->add_do_method(animation.ptr(), "value_track_set_update_mode", animation->get_track_count(), update_mode);
+ }
+ undo_redo->add_undo_method(animation.ptr(), "remove_track", animation->get_track_count());
+ undo_redo->commit_action();
}
}
@@ -5249,7 +5259,16 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
id.value = base->get_scale();
} break;
- case Animation::TYPE_BLEND_SHAPE:
+ case Animation::TYPE_BLEND_SHAPE: {
+ MeshInstance3D *base = Object::cast_to<MeshInstance3D>(node);
+
+ if (!base) {
+ EditorNode::get_singleton()->show_warning(TTR("Track is not of type MeshInstance3D, can't insert key"));
+ return;
+ }
+
+ id.value = base->get_blend_shape_value(base->find_blend_shape_by_name(id.path.get_subname(0)));
+ } break;
case Animation::TYPE_VALUE: {
NodePath bp;
_find_hint_for_track(p_track, bp, &id.value);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index cb647ffc35..8b6d316dd1 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3407,8 +3407,7 @@ void EditorNode::_discard_changes(const String &p_str) {
}
args.push_back("--project-manager");
- Error err = OS::get_singleton()->create_instance(args);
- ERR_FAIL_COND(err);
+ OS::get_singleton()->set_restart_on_exit(true, args);
} break;
case RELOAD_CURRENT_PROJECT: {
restart_editor();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index f9be1b08d9..1afe2ddda7 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1796,7 +1796,7 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
bool symmetric = m->is_alt_pressed();
Rect2 local_rect = ci->_edit_get_rect();
- real_t aspect = local_rect.get_size().y / local_rect.get_size().x;
+ real_t aspect = local_rect.has_area() ? (local_rect.get_size().y / local_rect.get_size().x) : (local_rect.get_size().y + 1.0) / (local_rect.get_size().x + 1.0);
Point2 current_begin = local_rect.get_position();
Point2 current_end = local_rect.get_position() + local_rect.get_size();
Point2 max_begin = (symmetric) ? (current_begin + current_end - ci->_edit_get_minimum_size()) / 2.0 : current_end - ci->_edit_get_minimum_size();
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 72eea8a27e..bd720cde93 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -1575,7 +1575,7 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
} else {
Node *node_owner = node->get_owner();
if (node == edited_scene || node_owner == edited_scene || (node_owner != nullptr && edited_scene->is_editable_instance(node_owner))) {
- if (selection_results.has(node)) {
+ if (!selection_results.has(node)) {
selection_results.append(node);
}
break;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index d7b88511d9..9d1576cdf2 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -412,7 +412,7 @@ void ShaderEditorPlugin::_close_builtin_shaders_from_scene(const String &p_scene
void ShaderEditorPlugin::_resource_saved(Object *obj) {
// May have been renamed on save.
for (EditedShader &edited_shader : edited_shaders) {
- if (edited_shader.shader.ptr() == obj) {
+ if (edited_shader.shader.ptr() == obj || edited_shader.shader_inc.ptr() == obj) {
_update_shader_list();
return;
}
diff --git a/main/main.cpp b/main/main.cpp
index c7c0c08fad..e42469b51b 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2634,10 +2634,12 @@ Error Main::setup2(bool p_show_boot_logo) {
}
}
- if (prefer_wayland) {
- display_driver = "wayland";
- } else {
- display_driver = "default";
+ if (display_driver.is_empty()) {
+ if (prefer_wayland) {
+ display_driver = "wayland";
+ } else {
+ display_driver = "default";
+ }
}
}
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 13707de12a..d8b44a558f 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1901,7 +1901,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
case GDScriptParser::Node::MATCH: {
const GDScriptParser::MatchNode *match = static_cast<const GDScriptParser::MatchNode *>(s);
- codegen.start_block(); // Add an extra block, since the binding pattern and @special variables belong to the branch scope.
+ codegen.start_block(); // Add an extra block, since @special locals belong to the match scope.
// Evaluate the match expression.
GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype(), codegen.script));
@@ -1939,7 +1939,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
const GDScriptParser::MatchBranchNode *branch = match->branches[j];
- codegen.start_block(); // Create an extra block around for binds.
+ codegen.start_block(); // Add an extra block, since binds belong to the match branch scope.
// Add locals in block before patterns, so temporaries don't use the stack address for binds.
List<GDScriptCodeGenerator::Address> branch_locals = _add_block_locals(codegen, branch->block);
@@ -1991,13 +1991,15 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
_clear_block_locals(codegen, branch_locals);
- codegen.end_block(); // Get out of extra block.
+ codegen.end_block(); // Get out of extra block for binds.
}
// End all nested `if`s.
for (int j = 0; j < match->branches.size(); j++) {
gen->write_endif();
}
+
+ codegen.end_block(); // Get out of extra block for match's @special locals.
} break;
case GDScriptParser::Node::IF: {
const GDScriptParser::IfNode *if_n = static_cast<const GDScriptParser::IfNode *>(s);
@@ -2031,7 +2033,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
case GDScriptParser::Node::FOR: {
const GDScriptParser::ForNode *for_n = static_cast<const GDScriptParser::ForNode *>(s);
- codegen.start_block(); // Add an extra block, since the iterator and @special variables belong to the loop scope.
+ // Add an extra block, since the iterator and @special locals belong to the loop scope.
+ // Also we use custom logic to clear block locals.
+ codegen.start_block();
GDScriptCodeGenerator::Address iterator = codegen.add_local(for_n->variable->name, _gdtype_from_datatype(for_n->variable->get_datatype(), codegen.script));
@@ -2064,11 +2068,13 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
_clear_block_locals(codegen, loop_locals); // Outside loop, after block - for `break` and normal exit.
- codegen.end_block(); // Get out of extra block.
+ codegen.end_block(); // Get out of extra block for loop iterator, @special locals, and custom locals clearing.
} break;
case GDScriptParser::Node::WHILE: {
const GDScriptParser::WhileNode *while_n = static_cast<const GDScriptParser::WhileNode *>(s);
+ codegen.start_block(); // Add an extra block, since we use custom logic to clear block locals.
+
gen->start_while_condition();
GDScriptCodeGenerator::Address condition = _parse_expression(codegen, err, while_n->condition);
@@ -2095,6 +2101,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
gen->write_endwhile();
_clear_block_locals(codegen, loop_locals); // Outside loop, after block - for `break` and normal exit.
+
+ codegen.end_block(); // Get out of extra block for custom locals clearing.
} break;
case GDScriptParser::Node::BREAK: {
gen->write_break();
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 28a030e492..822fc412b4 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -402,7 +402,9 @@ void GDScriptLanguage::debug_get_globals(List<String> *p_globals, List<Variant>
}
const Variant &var = gl_array[E.value];
- if (Object *obj = var) {
+ bool freed = false;
+ const Object *obj = var.get_validated_object_with_check(freed);
+ if (obj && !freed) {
if (Object::cast_to<GDScriptNativeClass>(obj)) {
continue;
}
diff --git a/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd
new file mode 100644
index 0000000000..3724c8c713
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/90086
+
+class MyObj:
+ var obj: WeakRef
+
+func test():
+ var obj_1 = MyObj.new()
+ var obj_2 = MyObj.new()
+ obj_1.obj = obj_2
diff --git a/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out
new file mode 100644
index 0000000000..dfca5b1eca
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/errors/invalid_property_assignment.out
@@ -0,0 +1,6 @@
+GDTEST_RUNTIME_ERROR
+>> SCRIPT ERROR
+>> on function: test()
+>> runtime/errors/invalid_property_assignment.gd
+>> 9
+>> Invalid assignment of property or key 'obj' with value of type 'RefCounted (MyObj)' on a base object of type 'RefCounted (MyObj)'.
diff --git a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
index c774ebf83c..df639a7b4d 100644
--- a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.gd
@@ -1,6 +1,5 @@
# GH-77666
-
-func test():
+func test_exit_if():
var ref := RefCounted.new()
print(ref.get_reference_count())
@@ -8,3 +7,20 @@ func test():
var _temp := ref
print(ref.get_reference_count())
+
+# GH-94654
+func test_exit_while():
+ var slots_data := []
+
+ while true:
+ @warning_ignore("confusable_local_declaration")
+ var slot = 42
+ slots_data.append(slot)
+ break
+
+ var slot: int = slots_data[0]
+ print(slot)
+
+func test():
+ test_exit_if()
+ test_exit_while()
diff --git a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
index 04b4638adf..164eb24963 100644
--- a/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
+++ b/modules/gdscript/tests/scripts/runtime/features/reset_local_var_on_exit_block.out
@@ -1,3 +1,4 @@
GDTEST_OK
1
1
+42
diff --git a/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd
new file mode 100644
index 0000000000..e1aba83507
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.gd
@@ -0,0 +1,11 @@
+# https://github.com/godotengine/godot/issues/90086
+
+class MyObj:
+ var obj : WeakRef
+
+func test():
+ var obj_1 = MyObj.new()
+ var obj_2 = MyObj.new()
+ assert(obj_2.get_reference_count() == 1)
+ obj_1.set(&"obj", obj_2)
+ assert(obj_2.get_reference_count() == 1)
diff --git a/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out
new file mode 100644
index 0000000000..d73c5eb7cd
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/set_does_not_leak.out
@@ -0,0 +1 @@
+GDTEST_OK
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index f70e440781..ec3ea9bcae 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -57,7 +57,7 @@
static bool _get_blender_version(const String &p_path, int &r_major, int &r_minor, String *r_err = nullptr) {
if (!FileAccess::exists(p_path)) {
if (r_err) {
- *r_err = TTR("Path does not contain a Blender installation.");
+ *r_err = TTR("Path does not point to a valid executable.");
}
return false;
}
@@ -67,14 +67,14 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino
Error err = OS::get_singleton()->execute(p_path, args, &pipe);
if (err != OK) {
if (r_err) {
- *r_err = TTR("Can't execute Blender binary.");
+ *r_err = TTR("Couldn't run Blender executable.");
}
return false;
}
int bl = pipe.find("Blender ");
if (bl == -1) {
if (r_err) {
- *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s."), p_path);
+ *r_err = vformat(TTR("Unexpected --version output from Blender executable at: %s."), p_path);
}
return false;
}
@@ -83,7 +83,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino
int pp = pipe.find(".");
if (pp == -1) {
if (r_err) {
- *r_err = TTR("Path supplied lacks a Blender binary.");
+ *r_err = vformat(TTR("Couldn't extract version information from Blender executable at: %s."), p_path);
}
return false;
}
@@ -91,7 +91,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino
r_major = v.to_int();
if (r_major < 3) {
if (r_err) {
- *r_err = TTR("This Blender installation is too old for this importer (not 3.0+).");
+ *r_err = vformat(TTR("Found Blender version %d.x, which is too old for this importer (3.0+ is required)."), r_major);
}
return false;
}
@@ -392,9 +392,9 @@ void EditorFileSystemImportFormatSupportQueryBlend::_validate_path(String p_path
if (_test_blender_path(p_path, &error)) {
success = true;
if (auto_detected_path == p_path) {
- error = TTR("Path to Blender installation is valid (Autodetected).");
+ error = TTR("Path to Blender executable is valid (Autodetected).");
} else {
- error = TTR("Path to Blender installation is valid.");
+ error = TTR("Path to Blender executable is valid.");
}
}
}
@@ -490,11 +490,15 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
if (!configure_blender_dialog) {
configure_blender_dialog = memnew(ConfirmationDialog);
configure_blender_dialog->set_title(TTR("Configure Blender Importer"));
- configure_blender_dialog->set_flag(Window::FLAG_BORDERLESS, true); // Avoid closing accidentally .
+ configure_blender_dialog->set_flag(Window::FLAG_BORDERLESS, true); // Avoid closing accidentally.
configure_blender_dialog->set_close_on_escape(false);
+ String select_exec_label = TTR("Blender 3.0+ is required to import '.blend' files.\nPlease provide a valid path to a Blender executable.");
+#ifdef MACOS_ENABLED
+ select_exec_label += "\n" + TTR("On macOS, this should be the `Contents/MacOS/blender` file within the Blender `.app` folder.");
+#endif
VBoxContainer *vb = memnew(VBoxContainer);
- vb->add_child(memnew(Label(TTR("Blender 3.0+ is required to import '.blend' files.\nPlease provide a valid path to a Blender installation:"))));
+ vb->add_child(memnew(Label(select_exec_label)));
HBoxContainer *hb = memnew(HBoxContainer);
@@ -528,8 +532,8 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
browse_dialog = memnew(EditorFileDialog);
browse_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
- browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
- browse_dialog->connect("dir_selected", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_select_install));
+ browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ browse_dialog->connect("file_selected", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_select_install));
EditorNode::get_singleton()->get_gui_base()->add_child(browse_dialog);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index 50bf56d832..f5b64ff81b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -869,7 +869,7 @@ namespace Godot
}
/// <summary>
- /// Multiplies each component of the <see cref="Vector2"/>
+ /// Divides each component of the <see cref="Vector2"/>
/// by the given <see cref="real_t"/>.
/// </summary>
/// <param name="vec">The dividend vector.</param>
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index a0da9019c6..5169b9417f 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -2323,7 +2323,8 @@ static bool has_valid_keystore_credentials(String &r_error_str, const String &p_
args.push_back(p_password);
args.push_back("-alias");
args.push_back(p_username);
- Error error = OS::get_singleton()->execute("keytool", args, &output, nullptr, true);
+ String keytool_path = EditorExportPlatformAndroid::get_keytool_path();
+ Error error = OS::get_singleton()->execute(keytool_path, args, &output, nullptr, true);
String keytool_error = "keytool error:";
bool valid = output.substr(0, keytool_error.length()) != keytool_error;
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index b91b023ce6..f5555289fd 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -301,7 +301,7 @@ task generateGodotTemplates {
*/
task generateDevTemplate {
// add parameter to set symbols to true
- gradle.startParameter.projectProperties += [doNotStrip: "true"]
+ project.ext.doNotStrip = "true"
gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
dependsOn = generateBuildTasks("template")
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index d6eb101a68..4a52e26373 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1735,7 +1735,7 @@ Vector<DisplayServer::WindowID> DisplayServerX11::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
@@ -1749,6 +1749,11 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
rendering_device->screen_create(id);
}
#endif
+
+ if (p_transient_parent != INVALID_WINDOW_ID) {
+ window_set_transient(id, p_transient_parent);
+ }
+
return id;
}
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 341ba5f079..0cbfbe51ef 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -438,7 +438,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override;
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index b4741dc08f..bd3c6af273 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -326,7 +326,7 @@ public:
virtual Vector<int> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_id) override;
virtual void delete_sub_window(WindowID p_id) override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index da45391995..cd2d8a60ac 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -1714,7 +1714,7 @@ Vector<DisplayServer::WindowID> DisplayServerMacOS::get_window_list() const {
return ret;
}
-DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_vsync_mode, p_rect);
@@ -1728,6 +1728,12 @@ DisplayServer::WindowID DisplayServerMacOS::create_sub_window(WindowMode p_mode,
rendering_device->screen_create(id);
}
#endif
+
+ window_set_exclusive(id, p_exclusive);
+ if (p_transient_parent != INVALID_WINDOW_ID) {
+ window_set_transient(id, p_transient_parent);
+ }
+
return id;
}
diff --git a/platform/web/detect.py b/platform/web/detect.py
index 79485ea28a..bf75c2f9fc 100644
--- a/platform/web/detect.py
+++ b/platform/web/detect.py
@@ -227,6 +227,11 @@ def configure(env: "SConsEnvironment"):
env.Append(LINKFLAGS=["-sDEFAULT_PTHREAD_STACK_SIZE=%sKB" % env["default_pthread_stack_size"]])
env.Append(LINKFLAGS=["-sPTHREAD_POOL_SIZE=8"])
env.Append(LINKFLAGS=["-sWASM_MEM_MAX=2048MB"])
+ if not env["dlink_enabled"]:
+ # Workaround https://github.com/emscripten-core/emscripten/issues/21844#issuecomment-2116936414.
+ # Not needed (and potentially dangerous) when dlink_enabled=yes, since we set EXPORT_ALL=1 in that case.
+ env.Append(LINKFLAGS=["-sEXPORTED_FUNCTIONS=['__emscripten_thread_crashed','_main']"])
+
elif env["proxy_to_pthread"]:
print_warning('"threads=no" support requires "proxy_to_pthread=no", disabling proxy to pthread.')
env["proxy_to_pthread"] = False
diff --git a/platform/web/js/libs/library_godot_audio.js b/platform/web/js/libs/library_godot_audio.js
index 0b16b07261..66d0d3d79d 100644
--- a/platform/web/js/libs/library_godot_audio.js
+++ b/platform/web/js/libs/library_godot_audio.js
@@ -77,7 +77,7 @@ class Sample {
* Creates a `Sample` based on the params. Will register it to the
* `GodotAudio.samples` registry.
* @param {SampleParams} params Base params
- * @param {SampleOptions} [options={}] Optional params
+ * @param {SampleOptions} [options={{}}] Optional params
* @returns {Sample}
*/
static create(params, options = {}) {
@@ -98,8 +98,7 @@ class Sample {
/**
* `Sample` constructor.
* @param {SampleParams} params Base params
- * @param {SampleOptions} [options={}] Optional params
- * @constructor
+ * @param {SampleOptions} [options={{}}] Optional params
*/
constructor(params, options = {}) {
/** @type {string} */
@@ -154,7 +153,7 @@ class Sample {
if (this._audioBuffer == null) {
throw new Error('couldn\'t duplicate a null audioBuffer');
}
- /** @type {Float32Array[]} */
+ /** @type {Array<Float32Array>} */
const channels = new Array(this._audioBuffer.numberOfChannels);
for (let i = 0; i < this._audioBuffer.numberOfChannels; i++) {
const channel = new Float32Array(this._audioBuffer.getChannelData(i));
@@ -189,7 +188,6 @@ class SampleNodeBus {
/**
* `SampleNodeBus` constructor.
* @param {Bus} bus The bus related to the new `SampleNodeBus`.
- * @constructor
*/
constructor(bus) {
const NUMBER_OF_WEB_CHANNELS = 6;
@@ -413,8 +411,7 @@ class SampleNode {
/**
* @param {SampleNodeParams} params Base params
- * @param {SampleNodeOptions} [options={}] Optional params
- * @constructor
+ * @param {SampleNodeOptions} [options={{}}] Optional params
*/
constructor(params, options = {}) {
/** @type {string} */
@@ -441,7 +438,7 @@ class SampleNode {
this._sampleNodeBuses = new Map();
/** @type {AudioBufferSourceNode | null} */
this._source = GodotAudio.ctx.createBufferSource();
- /** @type {AudioBufferSourceNode["onended"]} */
+
this._onended = null;
this.setPlaybackRate(options.playbackRate ?? 44100);
@@ -558,7 +555,7 @@ class SampleNode {
/**
* Sets the volumes of the `SampleNode` for each buses passed in parameters.
- * @param {Bus[]} buses
+ * @param {Array<Bus>} buses
* @param {Float32Array} volumes
*/
setVolumes(buses, volumes) {
@@ -818,7 +815,6 @@ class Bus {
/**
* `Bus` constructor.
- * @constructor
*/
constructor() {
/** @type {Set<SampleNode>} */
@@ -985,7 +981,6 @@ class Bus {
GodotAudio.buses = GodotAudio.buses.filter((v) => v !== this);
}
- /** @type {Bus["prototype"]["_syncSampleNodes"]} */
_syncSampleNodes() {
const sampleNodes = Array.from(this._sampleNodes);
for (let i = 0; i < sampleNodes.length; i++) {
@@ -1086,7 +1081,7 @@ const _GodotAudio = {
// `Bus` class
/**
* Registry of `Bus`es.
- * @type {Bus[]}
+ * @type {Array<Bus>}
*/
buses: null,
/**
@@ -1309,7 +1304,7 @@ const _GodotAudio = {
/**
* Triggered when a sample node volumes need to be updated.
* @param {string} playbackObjectId Id of the sample playback
- * @param {number[]} busIndexes Indexes of the buses that need to be updated
+ * @param {Array<number>} busIndexes Indexes of the buses that need to be updated
* @param {Float32Array} volumes Array of the volumes
* @returns {void}
*/
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index bfbf7d3ebc..b4830c5908 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -589,7 +589,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
"libEGL.windows." + env["arch"] + prebuilt_lib_extra_suffix,
"libGLES.windows." + env["arch"] + prebuilt_lib_extra_suffix,
]
- LIBS += ["dxgi", "d3d9", "d3d11", "synchronization"]
+ LIBS += ["dxgi", "d3d9", "d3d11"]
env.Prepend(CPPPATH=["#thirdparty/angle/include"])
if env["target"] in ["editor", "template_debug"]:
@@ -817,7 +817,7 @@ def configure_mingw(env: "SConsEnvironment"):
"ANGLE.windows." + env["arch"],
]
)
- env.Append(LIBS=["dxgi", "d3d9", "d3d11", "synchronization"])
+ env.Append(LIBS=["dxgi", "d3d9", "d3d11"])
env.Prepend(CPPPATH=["#thirdparty/angle/include"])
env.Append(CPPDEFINES=["MINGW_ENABLED", ("MINGW_HAS_SECURE_API", 1)])
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index ae8d1cace0..020ef0c31b 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1306,10 +1306,10 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons
return INVALID_WINDOW_ID;
}
-DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
_THREAD_SAFE_METHOD_
- WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect);
+ WindowID window_id = _create_window(p_mode, p_vsync_mode, p_flags, p_rect, p_exclusive, p_transient_parent);
ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window.");
WindowData &wd = windows[window_id];
@@ -5326,7 +5326,7 @@ void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const
}
}
-DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
DWORD dwExStyle;
DWORD dwStyle;
@@ -5376,6 +5376,18 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowID id = window_id_counter;
{
+ WindowData *wd_transient_parent = nullptr;
+ HWND owner_hwnd = nullptr;
+ if (p_transient_parent != INVALID_WINDOW_ID && !windows.has(p_transient_parent)) {
+ ERR_PRINT("Condition \"!windows.has(p_transient_parent)\" is true.");
+ p_transient_parent = INVALID_WINDOW_ID;
+ } else {
+ wd_transient_parent = &windows[p_transient_parent];
+ if (p_exclusive) {
+ owner_hwnd = wd_transient_parent->hWnd;
+ }
+ }
+
WindowData &wd = windows[id];
wd.hWnd = CreateWindowExW(
@@ -5386,7 +5398,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
WindowRect.top,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
- nullptr,
+ owner_hwnd,
nullptr,
hInstance,
// tunnel the WindowData we need to handle creation message
@@ -5408,6 +5420,12 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd.pre_fs_valid = true;
}
+ wd.exclusive = p_exclusive;
+ if (wd_transient_parent) {
+ wd.transient_parent = p_transient_parent;
+ wd_transient_parent->transient_children.insert(id);
+ }
+
if (is_dark_mode_supported() && dark_title_available) {
BOOL value = is_dark_mode();
::DwmSetWindowAttribute(wd.hWnd, use_legacy_dark_mode_before_20H1 ? DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 : DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
@@ -6063,7 +6081,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
window_position = scr_rect.position + (scr_rect.size - p_resolution) / 2;
}
- WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution));
+ WindowID main_window = _create_window(p_mode, p_vsync_mode, p_flags, Rect2i(window_position, p_resolution), false, INVALID_WINDOW_ID);
ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window.");
joypad = new JoypadWindows(&windows[MAIN_WINDOW_ID].hWnd);
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 650f0412ea..7b259def14 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -517,7 +517,7 @@ class DisplayServerWindows : public DisplayServer {
uint64_t time_since_popup = 0;
Ref<Image> icon;
- WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
+ WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent);
WindowID window_id_counter = MAIN_WINDOW_ID;
RBMap<WindowID, WindowData> windows;
@@ -652,7 +652,7 @@ public:
virtual Vector<DisplayServer::WindowID> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override;
virtual void show_window(WindowID p_window) override;
virtual void delete_sub_window(WindowID p_window) override;
diff --git a/platform/windows/gl_manager_windows_native.cpp b/platform/windows/gl_manager_windows_native.cpp
index f74aa4ced7..8590c46d12 100644
--- a/platform/windows/gl_manager_windows_native.cpp
+++ b/platform/windows/gl_manager_windows_native.cpp
@@ -243,7 +243,7 @@ void GLManagerNative_Windows::_nvapi_setup_profile() {
}
}
- NVDRS_SETTING ogl_thread_control_setting = { 0 };
+ NVDRS_SETTING ogl_thread_control_setting = {};
ogl_thread_control_setting.version = NVDRS_SETTING_VER;
ogl_thread_control_setting.settingId = OGL_THREAD_CONTROL_ID;
ogl_thread_control_setting.settingType = NVDRS_DWORD_TYPE;
@@ -259,7 +259,7 @@ void GLManagerNative_Windows::_nvapi_setup_profile() {
return;
}
- NVDRS_SETTING vrr_mode_setting = { 0 };
+ NVDRS_SETTING vrr_mode_setting = {};
vrr_mode_setting.version = NVDRS_SETTING_VER;
vrr_mode_setting.settingId = VRR_MODE_ID;
vrr_mode_setting.settingType = NVDRS_DWORD_TYPE;
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 59ebf38253..a27da73b89 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -138,15 +138,11 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
bool p_seek = p_playback_info.seeked;
bool p_is_external_seeking = p_playback_info.is_external_seeking;
- bool is_just_looped = false;
-
// 1. Progress for AnimationNode.
+ bool will_end = Animation::is_greater_or_equal_approx(cur_time + cur_delta, cur_len);
if (cur_loop_mode != Animation::LOOP_NONE) {
if (cur_loop_mode == Animation::LOOP_LINEAR) {
if (!Math::is_zero_approx(cur_len)) {
- if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
- is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
- }
cur_time = Math::fposmod(cur_time, cur_len);
}
backward = false;
@@ -156,7 +152,6 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
backward = !backward;
} else if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
backward = !backward;
- is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
}
cur_time = Math::pingpong(cur_time, cur_len);
}
@@ -190,7 +185,7 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
nti.position = cur_time;
nti.delta = cur_delta;
nti.loop_mode = cur_loop_mode;
- nti.is_just_looped = is_just_looped;
+ nti.will_end = will_end;
// 3. Progress for Animation.
double prev_playback_time = prev_time + start_offset;
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index ecf4054e23..c3c5399a6b 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -804,7 +804,7 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
pi.weight = 0;
current_nti = p_state_machine->blend_node(p_state_machine->states[current].node, current, pi, AnimationNode::FILTER_IGNORE, true, true);
// Don't process first node if not necessary, insteads process next node.
- _transition_to_next_recursive(tree, p_state_machine, p_test_only);
+ _transition_to_next_recursive(tree, p_state_machine, p_delta, p_test_only);
}
// Check current node existence.
@@ -881,7 +881,7 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
}
// Find next and see when to transition.
- bool will_end = _transition_to_next_recursive(tree, p_state_machine, p_test_only) || current == AnimationNodeStateMachine::END_NODE;
+ bool will_end = _transition_to_next_recursive(tree, p_state_machine, p_delta, p_test_only) || current == AnimationNodeStateMachine::END_NODE;
// Predict remaining time.
if (will_end || ((p_state_machine->get_state_machine_type() == AnimationNodeStateMachine::STATE_MACHINE_TYPE_NESTED) && !p_state_machine->has_transition_from(current))) {
@@ -899,10 +899,11 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
return current_nti;
}
-bool AnimationNodeStateMachinePlayback::_transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, bool p_test_only) {
+bool AnimationNodeStateMachinePlayback::_transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, double p_delta, bool p_test_only) {
_reset_request_for_fading_from = false;
AnimationMixer::PlaybackInfo pi;
+ pi.delta = p_delta;
NextInfo next;
Vector<StringName> transition_path;
transition_path.push_back(current);
diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h
index b58ff4d224..648e96b138 100644
--- a/scene/animation/animation_node_state_machine.h
+++ b/scene/animation/animation_node_state_machine.h
@@ -306,7 +306,7 @@ class AnimationNodeStateMachinePlayback : public Resource {
AnimationNode::NodeTimeInfo _process(const String &p_base_path, AnimationNodeStateMachine *p_state_machine, const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only);
bool _check_advance_condition(const Ref<AnimationNodeStateMachine> p_state_machine, const Ref<AnimationNodeStateMachineTransition> p_transition) const;
- bool _transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, bool p_test_only);
+ bool _transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, double p_delta, bool p_test_only);
NextInfo _find_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine) const;
Ref<AnimationNodeStateMachineTransition> _check_group_transition(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, const AnimationNodeStateMachine::Transition &p_transition, Ref<AnimationNodeStateMachine> &r_state_machine, bool &r_bypass) const;
bool _can_transition_to_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, NextInfo p_next, bool p_test_only);
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 69287478db..c5a6a99d07 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -46,9 +46,9 @@ void AnimationNode::get_parameter_list(List<PropertyInfo> *r_list) const {
}
}
- r_list->push_back(PropertyInfo(Variant::FLOAT, current_length, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
- r_list->push_back(PropertyInfo(Variant::FLOAT, current_position, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
- r_list->push_back(PropertyInfo(Variant::FLOAT, current_delta, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_READ_ONLY));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, current_length, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_READ_ONLY));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, current_position, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_READ_ONLY));
+ r_list->push_back(PropertyInfo(Variant::FLOAT, current_delta, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_READ_ONLY));
}
Variant AnimationNode::get_parameter_default_value(const StringName &p_parameter) const {
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 6698427233..aa497ff1d6 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -74,7 +74,7 @@ public:
// Needs internally to estimate remain time, the previous frame values are not retained.
Animation::LoopMode loop_mode = Animation::LOOP_NONE;
- bool is_just_looped = false; // For breaking loop, it is true when just looped.
+ bool will_end = false; // For breaking loop, it is true when just looped.
bool is_infinity = false; // For unpredictable state machine's end.
bool is_looping() {
@@ -84,7 +84,7 @@ public:
if ((is_looping() && !p_break_loop) || is_infinity) {
return HUGE_LENGTH;
}
- if (p_break_loop && is_just_looped) {
+ if (is_looping() && p_break_loop && will_end) {
return 0;
}
double remain = length - position;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 3f1b9fc981..8a1a531c92 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -6863,9 +6863,9 @@ void TextEdit::_bind_methods() {
ADD_GROUP("Scroll", "scroll_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enabled", "is_smooth_scroll_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_v_scroll_speed", "get_v_scroll_speed");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:lines/s"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_past_end_of_file"), "set_scroll_past_end_of_file_enabled", "is_scroll_past_end_of_file_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:lines"), "set_v_scroll", "get_v_scroll");
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_horizontal", PROPERTY_HINT_NONE, "suffix:px"), "set_h_scroll", "get_h_scroll");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_fit_content_height"), "set_fit_content_height_enabled", "is_fit_content_height_enabled");
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index d409efbfab..e5873f0e9a 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -631,7 +631,7 @@ void Window::_make_window() {
window_rect = Rect2i(DisplayServer::get_singleton()->screen_get_position(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) + (DisplayServer::get_singleton()->screen_get_size(DisplayServer::SCREEN_WITH_KEYBOARD_FOCUS) - size) / 2, size);
}
- window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect);
+ window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), vsync_mode, f, window_rect, is_in_edited_scene_root() ? false : exclusive, transient_parent ? transient_parent->window_id : DisplayServer::INVALID_WINDOW_ID);
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
@@ -639,18 +639,8 @@ void Window::_make_window() {
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
- if (is_in_edited_scene_root()) {
- DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
- } else {
- DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
- }
-
_update_window_size();
- if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) {
- DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id);
- }
-
if (transient_parent) {
for (const Window *E : transient_children) {
if (E->window_id != DisplayServer::INVALID_WINDOW_ID) {
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 84c091e320..fd6cdb451e 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -329,7 +329,7 @@ private:
friend class AudioDriver;
void _driver_process(int p_frames, int32_t *p_buffer);
- LocalVector<Ref<AudioStreamPlayback>> sample_playback_list;
+ LocalVector<Ref<AudioSamplePlayback>> sample_playback_list;
protected:
static void _bind_methods();
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index d362a4073a..5451057645 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -570,7 +570,7 @@ int DisplayServer::get_screen_from_rect(const Rect2 &p_rect) const {
return pos_screen;
}
-DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect) {
+DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect, bool p_exclusive, WindowID p_transient_parent) {
ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server.");
}
diff --git a/servers/display_server.h b/servers/display_server.h
index 8c7e92fdc3..d0fe76faff 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -396,7 +396,7 @@ public:
WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH),
};
- virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
+ virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID);
virtual void show_window(WindowID p_id);
virtual void delete_sub_window(WindowID p_id);
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 60422c16cc..a5277479ca 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -85,7 +85,7 @@ public:
Vector<DisplayServer::WindowID> get_window_list() const override { return Vector<DisplayServer::WindowID>(); }
- WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override { return 0; }
+ WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i(), bool p_exclusive = false, WindowID p_transient_parent = INVALID_WINDOW_ID) override { return 0; }
void show_window(WindowID p_id) override {}
void delete_sub_window(WindowID p_id) override {}
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index a4ee33ecc0..2542f2eed7 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -1286,6 +1286,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
break;
}
if (function->arguments[j].tex_argument_check) {
+ if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ is_screen_texture = true;
+ } else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ is_depth_texture = true;
+ } else if (function->arguments[j].tex_hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ is_normal_roughness_texture = true;
+ }
sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat);
found = true;
break;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 745dcf5392..10c1158d95 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -4761,7 +4761,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
-bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) {
+bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat, ShaderNode::Uniform::Hint p_hint) {
for (int i = 0; i < shader->vfunctions.size(); i++) {
if (shader->vfunctions[i].name == p_name) {
ERR_FAIL_INDEX_V(p_argument, shader->vfunctions[i].function->arguments.size(), false);
@@ -4770,20 +4770,21 @@ bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(const Str
_set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."), p_argument, String(p_name)));
return false;
} else if (arg->tex_argument_check) {
- //was checked, verify that filter and repeat are the same
- if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) {
+ // Was checked, verify that filter, repeat, and hint are the same.
+ if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat && arg->tex_hint == p_hint) {
return true;
} else {
- _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using textures that differ in either filter or repeat setting."), p_argument, String(p_name)));
+ _set_error(vformat(RTR("Sampler argument %d of function '%s' called more than once using textures that differ in either filter, repeat, or texture hint setting."), p_argument, String(p_name)));
return false;
}
} else {
arg->tex_argument_check = true;
arg->tex_argument_filter = p_filter;
arg->tex_argument_repeat = p_repeat;
+ arg->tex_hint = p_hint;
for (KeyValue<StringName, HashSet<int>> &E : arg->tex_argument_connect) {
for (const int &F : E.value) {
- if (!_propagate_function_call_sampler_uniform_settings(E.key, F, p_filter, p_repeat)) {
+ if (!_propagate_function_call_sampler_uniform_settings(E.key, F, p_filter, p_repeat, p_hint)) {
return false;
}
}
@@ -5583,7 +5584,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
//propagate
- if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) {
+ if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat, u->hint)) {
return nullptr;
}
} else if (p_function_info.built_ins.has(varname)) {
@@ -7411,6 +7412,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
return ERR_PARSE_ERROR;
}
tk = _get_token();
+ } else {
+ _set_expected_error("(");
+ return ERR_PARSE_ERROR;
}
}
} else {
@@ -9520,6 +9524,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(RTR("Array size mismatch."));
return ERR_PARSE_ERROR;
}
+ } else {
+ _set_expected_error("(");
+ return ERR_PARSE_ERROR;
}
array_size = constant.array_size;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index bc0aa0558a..40f524ec9d 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -578,42 +578,6 @@ public:
Node(NODE_TYPE_STRUCT) {}
};
- struct FunctionNode : public Node {
- struct Argument {
- ArgumentQualifier qualifier;
- StringName name;
- DataType type;
- StringName struct_name;
- DataPrecision precision;
- //for passing textures as arguments
- bool tex_argument_check;
- TextureFilter tex_argument_filter;
- TextureRepeat tex_argument_repeat;
- bool tex_builtin_check;
- StringName tex_builtin;
- bool is_const;
- int array_size;
-
- HashMap<StringName, HashSet<int>> tex_argument_connect;
- };
-
- StringName name;
- 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(NODE_TYPE_FUNCTION) {}
- };
-
struct ShaderNode : public Node {
struct Constant {
StringName name;
@@ -722,6 +686,43 @@ public:
Node(NODE_TYPE_SHADER) {}
};
+ struct FunctionNode : public Node {
+ struct Argument {
+ ArgumentQualifier qualifier;
+ StringName name;
+ DataType type;
+ StringName struct_name;
+ DataPrecision precision;
+ //for passing textures as arguments
+ bool tex_argument_check;
+ TextureFilter tex_argument_filter;
+ TextureRepeat tex_argument_repeat;
+ bool tex_builtin_check;
+ StringName tex_builtin;
+ ShaderNode::Uniform::Hint tex_hint;
+ bool is_const;
+ int array_size;
+
+ HashMap<StringName, HashSet<int>> tex_argument_connect;
+ };
+
+ StringName name;
+ 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(NODE_TYPE_FUNCTION) {}
+ };
+
struct UniformOrderComparator {
_FORCE_INLINE_ bool operator()(const Pair<StringName, int> &A, const Pair<StringName, int> &B) const {
return A.second < B.second;
@@ -1122,7 +1123,7 @@ private:
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 *r_is_custom_function = nullptr);
bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr);
- bool _propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
+ bool _propagate_function_call_sampler_uniform_settings(const StringName &p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat, ShaderNode::Uniform::Hint p_hint);
bool _propagate_function_call_sampler_builtin_reference(const StringName &p_name, int p_argument, const StringName &p_builtin);
bool _validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message);
bool _check_node_constness(const Node *p_node) const;
diff --git a/tests/scene/test_graph_node.h b/tests/scene/test_graph_node.h
index bf6cc9be09..7973ac1444 100644
--- a/tests/scene/test_graph_node.h
+++ b/tests/scene/test_graph_node.h
@@ -48,8 +48,10 @@ TEST_CASE("[GraphNode][SceneTree]") {
test_node->add_child(test_child);
// Test.
- CHECK_NOTHROW_MESSAGE(test_node->remove_child(test_child));
+ test_node->remove_child(test_child);
+ CHECK(test_node->get_child_count(false) == 0);
+ memdelete(test_child);
memdelete(test_node);
}
}