Browse Source

Merge pull request #85784 from YuriSizov/4.2-cherrypicks

Cherry-picks for the 4.2 branch (future 4.2.1) - 1st batch
Rémi Verschelde 1 year ago
parent
commit
9d22668b9f
100 changed files with 602 additions and 325 deletions
  1. 1 2
      .github/CODEOWNERS
  2. 2 3
      core/io/resource_loader.cpp
  3. 2 3
      core/io/resource_saver.cpp
  4. 5 3
      core/object/message_queue.cpp
  5. 4 0
      core/object/script_language.cpp
  6. 5 1
      core/string/translation.cpp
  7. 1 1
      core/templates/hashfuncs.h
  8. 6 6
      doc/classes/BaseMaterial3D.xml
  9. 1 1
      doc/classes/CameraAttributesPhysical.xml
  10. 10 8
      doc/classes/CanvasItem.xml
  11. 2 2
      doc/classes/EditorSettings.xml
  12. 6 0
      doc/classes/NavigationLink2D.xml
  13. 6 0
      doc/classes/NavigationLink3D.xml
  14. 8 1
      doc/classes/NavigationRegion2D.xml
  15. 8 1
      doc/classes/NavigationRegion3D.xml
  16. 10 6
      doc/classes/RenderingServer.xml
  17. 0 1
      doc/classes/VideoStreamPlayer.xml
  18. 6 4
      doc/classes/Viewport.xml
  19. 10 8
      doc/classes/VisualShaderNodeTextureParameter.xml
  20. 11 16
      doc/tools/make_rst.py
  21. 2 0
      drivers/gles3/rasterizer_scene_gles3.cpp
  22. 25 6
      drivers/gles3/shaders/scene.glsl
  23. 11 11
      drivers/gles3/storage/material_storage.cpp
  24. 11 12
      drivers/gles3/storage/mesh_storage.cpp
  25. 5 2
      drivers/vulkan/rendering_device_vulkan.cpp
  26. 8 3
      drivers/vulkan/rendering_device_vulkan.h
  27. 19 23
      editor/editor_about.cpp
  28. 0 2
      editor/editor_about.h
  29. 5 6
      editor/editor_autoload_settings.cpp
  30. 6 7
      editor/editor_command_palette.cpp
  31. 1 2
      editor/editor_command_palette.h
  32. 3 3
      editor/editor_node.cpp
  33. 8 0
      editor/editor_properties_array_dict.cpp
  34. 4 5
      editor/editor_quick_open.cpp
  35. 0 2
      editor/editor_quick_open.h
  36. 2 2
      editor/export/editor_export_platform.cpp
  37. 6 6
      editor/export/project_export.cpp
  38. 0 1
      editor/export/project_export.h
  39. 8 1
      editor/filesystem_dock.cpp
  40. 18 7
      editor/gui/scene_tree_editor.cpp
  41. 1 1
      editor/gui/scene_tree_editor.h
  42. 1 1
      editor/icons/SnapGrid.svg
  43. 2 0
      editor/import/resource_importer_scene.cpp
  44. 3 1
      editor/import/resource_importer_wav.cpp
  45. 3 3
      editor/input_event_configuration_dialog.cpp
  46. 3 0
      editor/plugins/gpu_particles_3d_editor_plugin.cpp
  47. 3 0
      editor/plugins/multimesh_editor_plugin.cpp
  48. 6 1
      editor/plugins/node_3d_editor_plugin.cpp
  49. 3 0
      editor/plugins/path_3d_editor_plugin.cpp
  50. 44 9
      editor/plugins/polygon_2d_editor_plugin.cpp
  51. 3 1
      editor/plugins/polygon_2d_editor_plugin.h
  52. 1 1
      editor/plugins/script_text_editor.cpp
  53. 6 2
      editor/plugins/tiles/tile_map_editor.cpp
  54. 1 6
      editor/project_manager.cpp
  55. 6 1
      editor/scene_tree_dock.cpp
  56. 15 26
      editor/shader_create_dialog.cpp
  57. 0 1
      editor/shader_create_dialog.h
  58. 6 8
      main/main.cpp
  59. 10 3
      methods.py
  60. 1 1
      modules/csg/csg_shape.cpp
  61. 13 0
      modules/gdscript/gdscript.cpp
  62. 26 3
      modules/gdscript/gdscript_editor.cpp
  63. 5 6
      modules/gdscript/tests/gdscript_test_runner.cpp
  64. 12 1
      modules/navigation/nav_map.cpp
  65. 0 1
      modules/openxr/action_map/openxr_action_map.cpp
  66. 2 0
      modules/tinyexr/image_loader_tinyexr.cpp
  67. 18 1
      modules/zip/zip_packer.cpp
  68. 14 8
      platform/ios/export/export_plugin.cpp
  69. 1 1
      platform/linuxbsd/x11/display_server_x11.cpp
  70. 2 1
      platform/macos/display_server_macos.mm
  71. 3 9
      platform/macos/export/export_plugin.cpp
  72. 1 1
      platform/macos/gl_manager_macos_angle.mm
  73. 1 1
      platform/windows/detect.py
  74. 1 3
      platform/windows/display_server_windows.cpp
  75. 7 5
      scene/2d/navigation_agent_2d.cpp
  76. 12 0
      scene/2d/navigation_link_2d.cpp
  77. 1 0
      scene/2d/navigation_link_2d.h
  78. 4 4
      scene/2d/navigation_obstacle_2d.cpp
  79. 11 1
      scene/2d/navigation_region_2d.cpp
  80. 1 0
      scene/2d/navigation_region_2d.h
  81. 1 1
      scene/2d/tile_map.cpp
  82. 8 6
      scene/3d/navigation_agent_3d.cpp
  83. 12 0
      scene/3d/navigation_link_3d.cpp
  84. 2 0
      scene/3d/navigation_link_3d.h
  85. 5 7
      scene/3d/navigation_obstacle_3d.cpp
  86. 10 1
      scene/3d/navigation_region_3d.cpp
  87. 2 0
      scene/3d/navigation_region_3d.h
  88. 1 0
      scene/animation/animation_mixer.cpp
  89. 1 1
      scene/animation/animation_player.cpp
  90. 8 5
      scene/animation/tween.cpp
  91. 1 0
      scene/animation/tween.h
  92. 3 1
      scene/gui/rich_text_label.cpp
  93. 10 0
      scene/gui/video_stream_player.cpp
  94. 18 8
      scene/main/window.cpp
  95. 2 2
      scene/resources/camera_attributes.cpp
  96. 1 1
      scene/resources/importer_mesh.cpp
  97. 1 1
      scene/resources/material.cpp
  98. 14 9
      scene/resources/tile_set.cpp
  99. 1 0
      scene/resources/video_stream.cpp
  100. 2 2
      servers/rendering/renderer_rd/effects/ss_effects.cpp

+ 1 - 2
.github/CODEOWNERS

@@ -140,10 +140,9 @@ doc_classes/*                       @godotengine/documentation
 
 
 /platform/android/                  @godotengine/android
 /platform/android/                  @godotengine/android
 /platform/ios/                      @godotengine/ios
 /platform/ios/                      @godotengine/ios
-/platform/javascript/               @godotengine/html5
 /platform/linuxbsd/                 @godotengine/linux-bsd
 /platform/linuxbsd/                 @godotengine/linux-bsd
 /platform/macos/                    @godotengine/macos
 /platform/macos/                    @godotengine/macos
-/platform/uwp/                      @godotengine/uwp
+/platform/web/                      @godotengine/web
 /platform/windows/                  @godotengine/windows
 /platform/windows/                  @godotengine/windows
 
 
 # Scene
 # Scene

+ 2 - 3
core/io/resource_loader.cpp

@@ -1113,11 +1113,10 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
 	Ref<Script> s = res;
 	Ref<Script> s = res;
 	StringName ibt = s->get_instance_base_type();
 	StringName ibt = s->get_instance_base_type();
 	bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatLoader");
 	bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatLoader");
-	ERR_FAIL_COND_V_MSG(!valid_type, false, "Script does not inherit a CustomResourceLoader: " + script_path + ".");
+	ERR_FAIL_COND_V_MSG(!valid_type, false, vformat("Failed to add a custom resource loader, script '%s' does not inherit 'ResourceFormatLoader'.", script_path));
 
 
 	Object *obj = ClassDB::instantiate(ibt);
 	Object *obj = ClassDB::instantiate(ibt);
-
-	ERR_FAIL_NULL_V_MSG(obj, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
+	ERR_FAIL_NULL_V_MSG(obj, false, vformat("Failed to add a custom resource loader, cannot instantiate '%s'.", ibt));
 
 
 	Ref<ResourceFormatLoader> crl = Object::cast_to<ResourceFormatLoader>(obj);
 	Ref<ResourceFormatLoader> crl = Object::cast_to<ResourceFormatLoader>(obj);
 	crl->set_script(s);
 	crl->set_script(s);

+ 2 - 3
core/io/resource_saver.cpp

@@ -237,11 +237,10 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
 	Ref<Script> s = res;
 	Ref<Script> s = res;
 	StringName ibt = s->get_instance_base_type();
 	StringName ibt = s->get_instance_base_type();
 	bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatSaver");
 	bool valid_type = ClassDB::is_parent_class(ibt, "ResourceFormatSaver");
-	ERR_FAIL_COND_V_MSG(!valid_type, false, "Script does not inherit a CustomResourceSaver: " + script_path + ".");
+	ERR_FAIL_COND_V_MSG(!valid_type, false, vformat("Failed to add a custom resource saver, script '%s' does not inherit 'ResourceFormatSaver'.", script_path));
 
 
 	Object *obj = ClassDB::instantiate(ibt);
 	Object *obj = ClassDB::instantiate(ibt);
-
-	ERR_FAIL_NULL_V_MSG(obj, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
+	ERR_FAIL_NULL_V_MSG(obj, false, vformat("Failed to add a custom resource saver, cannot instantiate '%s'.", ibt));
 
 
 	Ref<ResourceFormatSaver> crl = Object::cast_to<ResourceFormatSaver>(obj);
 	Ref<ResourceFormatSaver> crl = Object::cast_to<ResourceFormatSaver>(obj);
 	crl->set_script(s);
 	crl->set_script(s);

+ 5 - 3
core/object/message_queue.cpp

@@ -35,6 +35,8 @@
 #include "core/object/class_db.h"
 #include "core/object/class_db.h"
 #include "core/object/script_language.h"
 #include "core/object/script_language.h"
 
 
+#include <stdio.h>
+
 #ifdef DEV_ENABLED
 #ifdef DEV_ENABLED
 // Includes safety checks to ensure that a queue set as a thread singleton override
 // Includes safety checks to ensure that a queue set as a thread singleton override
 // is only ever called from the thread it was set for.
 // is only ever called from the thread it was set for.
@@ -93,7 +95,7 @@ Error CallQueue::push_callablep(const Callable &p_callable, const Variant **p_ar
 
 
 	if ((page_bytes[pages_used - 1] + room_needed) > uint32_t(PAGE_SIZE_BYTES)) {
 	if ((page_bytes[pages_used - 1] + room_needed) > uint32_t(PAGE_SIZE_BYTES)) {
 		if (pages_used == max_pages) {
 		if (pages_used == max_pages) {
-			ERR_PRINT("Failed method: " + p_callable + ". Message queue out of memory. " + error_text);
+			fprintf(stderr, "Failed method: %s. Message queue out of memory. %s\n", String(p_callable).utf8().get_data(), error_text.utf8().get_data());
 			statistics();
 			statistics();
 			UNLOCK_MUTEX;
 			UNLOCK_MUTEX;
 			return ERR_OUT_OF_MEMORY;
 			return ERR_OUT_OF_MEMORY;
@@ -144,7 +146,7 @@ Error CallQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant
 			if (ObjectDB::get_instance(p_id)) {
 			if (ObjectDB::get_instance(p_id)) {
 				type = ObjectDB::get_instance(p_id)->get_class();
 				type = ObjectDB::get_instance(p_id)->get_class();
 			}
 			}
-			ERR_PRINT("Failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id) + ". Message queue out of memory. " + error_text);
+			fprintf(stderr, "Failed set: %s: %s target ID: %s. Message queue out of memory. %s\n", type.utf8().get_data(), String(p_prop).utf8().get_data(), itos(p_id).utf8().get_data(), error_text.utf8().get_data());
 			statistics();
 			statistics();
 
 
 			UNLOCK_MUTEX;
 			UNLOCK_MUTEX;
@@ -181,7 +183,7 @@ Error CallQueue::push_notification(ObjectID p_id, int p_notification) {
 
 
 	if ((page_bytes[pages_used - 1] + room_needed) > uint32_t(PAGE_SIZE_BYTES)) {
 	if ((page_bytes[pages_used - 1] + room_needed) > uint32_t(PAGE_SIZE_BYTES)) {
 		if (pages_used == max_pages) {
 		if (pages_used == max_pages) {
-			ERR_PRINT("Failed notification: " + itos(p_notification) + " target ID: " + itos(p_id) + ". Message queue out of memory. " + error_text);
+			fprintf(stderr, "Failed notification: %s target ID: %s. Message queue out of memory. %s\n", itos(p_notification).utf8().get_data(), itos(p_id).utf8().get_data(), error_text.utf8().get_data());
 			statistics();
 			statistics();
 			UNLOCK_MUTEX;
 			UNLOCK_MUTEX;
 			return ERR_OUT_OF_MEMORY;
 			return ERR_OUT_OF_MEMORY;

+ 4 - 0
core/object/script_language.cpp

@@ -631,6 +631,10 @@ bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const {
 void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const HashMap<StringName, Variant> &p_values) {
 void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const HashMap<StringName, Variant> &p_values) {
 	HashSet<StringName> new_values;
 	HashSet<StringName> new_values;
 	for (const PropertyInfo &E : p_properties) {
 	for (const PropertyInfo &E : p_properties) {
+		if (E.usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_CATEGORY)) {
+			continue;
+		}
+
 		StringName n = E.name;
 		StringName n = E.name;
 		new_values.insert(n);
 		new_values.insert(n);
 
 

+ 5 - 1
core/string/translation.cpp

@@ -518,8 +518,12 @@ String TranslationServer::get_country_name(const String &p_country) const {
 }
 }
 
 
 void TranslationServer::set_locale(const String &p_locale) {
 void TranslationServer::set_locale(const String &p_locale) {
-	locale = standardize_locale(p_locale);
+	String new_locale = standardize_locale(p_locale);
+	if (locale == new_locale) {
+		return;
+	}
 
 
+	locale = new_locale;
 	ResourceLoader::reload_translation_remaps();
 	ResourceLoader::reload_translation_remaps();
 
 
 	if (OS::get_singleton()->get_main_loop()) {
 	if (OS::get_singleton()->get_main_loop()) {

+ 1 - 1
core/templates/hashfuncs.h

@@ -310,7 +310,7 @@ struct HashMapHasherDefault {
 	static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
 	static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
 	static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
 	static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
 	static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
 	static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
-	static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.ptr()); }
+	static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); }
 	static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
 	static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
 	static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }

+ 6 - 6
doc/classes/BaseMaterial3D.xml

@@ -501,22 +501,22 @@
 			Represents the size of the [enum TextureParam] enum.
 			Represents the size of the [enum TextureParam] enum.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST" value="0" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST" value="0" enum="TextureFilter">
-			The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized.
+			The texture filter reads from the nearest pixel only. This makes the texture look pixelated from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR" value="1" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR" value="1" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels. Use this when you want to avoid a pixelated style, but do not want mipmaps.
+			The texture filter blends between the nearest 4 pixels. This makes the texture look smooth from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="2" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="2" enum="TextureFilter">
-			The texture filter reads from the nearest pixel in the nearest mipmap. The fastest way to read from textures with mipmaps.
+			The texture filter reads from the nearest pixel and blends between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look pixelated from up close, and smooth from a distance.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="3" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="3" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps. Use this for most cases as mipmaps are important to smooth out pixels that are far from the camera.
+			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look smooth from up close, and smooth from a distance.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="4" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="4" enum="TextureFilter">
-			The texture filter reads from the nearest pixel, but selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			The texture filter reads from the nearest pixel and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look pixelated from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. This is the slowest of the filtering options, but results in the highest quality texturing. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			The texture filter blends between the nearest 4 pixels and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look smooth from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_MAX" value="6" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_MAX" value="6" enum="TextureFilter">
 			Represents the size of the [enum TextureFilter] enum.
 			Represents the size of the [enum TextureFilter] enum.

+ 1 - 1
doc/classes/CameraAttributesPhysical.xml

@@ -32,7 +32,7 @@
 			Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
 			Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
 		</member>
 		</member>
 		<member name="exposure_shutter_speed" type="float" setter="set_shutter_speed" getter="get_shutter_speed" default="100.0">
 		<member name="exposure_shutter_speed" type="float" setter="set_shutter_speed" getter="get_shutter_speed" default="100.0">
-			Time for shutter to open and close, measured in seconds. A higher value will let in more light leading to a brighter image, while a lower amount will let in less light leading to a darker image.
+			Time for shutter to open and close, evaluated as [code]1 / shutter_speed[/code] seconds. A higher value will allow less light (leading to a darker image), while a lower value will allow more light (leading to a brighter image).
 			Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
 			Only available when [member ProjectSettings.rendering/lights_and_shadows/use_physical_light_units] is enabled.
 		</member>
 		</member>
 		<member name="frustum_far" type="float" setter="set_far" getter="get_far" default="4000.0">
 		<member name="frustum_far" type="float" setter="set_far" getter="get_far" default="4000.0">

+ 10 - 8
doc/classes/CanvasItem.xml

@@ -660,24 +660,26 @@
 			The [CanvasItem] will inherit the filter from its parent.
 			The [CanvasItem] will inherit the filter from its parent.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST" value="1" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST" value="1" enum="TextureFilter">
-			The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering. Useful for pixel art.
+			The texture filter reads from the nearest pixel only. This makes the texture look pixelated from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR" value="2" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR" value="2" enum="TextureFilter">
-			The texture filter blends between the nearest four pixels. Use this for most cases where you want to avoid a pixelated style.
+			The texture filter blends between the nearest 4 pixels. This makes the texture look smooth from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="TextureFilter">
-			The texture filter reads from the nearest pixel in the nearest mipmap. This is the fastest way to read from textures with mipmaps.
+			The texture filter reads from the nearest pixel and blends between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look pixelated from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="4" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="4" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps. Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
+			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look smooth from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="TextureFilter">
-			The texture filter reads from the nearest pixel, but selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
-			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_NEAREST_WITH_MIPMAPS] is usually more appropriate.
+			The texture filter reads from the nearest pixel and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look pixelated from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_NEAREST_WITH_MIPMAPS] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="6" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="6" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. This is the slowest of the filtering options, but results in the highest quality texturing. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
-			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_LINEAR_WITH_MIPMAPS] is usually more appropriate.
+			The texture filter blends between the nearest 4 pixels and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look smooth from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant TEXTURE_FILTER_LINEAR_WITH_MIPMAPS] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="TEXTURE_FILTER_MAX" value="7" enum="TextureFilter">
 		<constant name="TEXTURE_FILTER_MAX" value="7" enum="TextureFilter">
 			Represents the size of the [enum TextureFilter] enum.
 			Represents the size of the [enum TextureFilter] enum.

+ 2 - 2
doc/classes/EditorSettings.xml

@@ -665,8 +665,8 @@
 		<member name="interface/theme/icon_and_font_color" type="int" setter="" getter="">
 		<member name="interface/theme/icon_and_font_color" type="int" setter="" getter="">
 			The icon and font color scheme to use in the editor.
 			The icon and font color scheme to use in the editor.
 			- [b]Auto[/b] determines the color scheme to use automatically based on [member interface/theme/base_color].
 			- [b]Auto[/b] determines the color scheme to use automatically based on [member interface/theme/base_color].
-			- [b]Dark[/b] makes fonts and icons light (suitable for dark themes).
-			- [b]Light[/b] makes fonts and icons dark (suitable for light themes). Icon colors are automatically converted by the editor following [url=https://github.com/godotengine/godot/blob/master/editor/editor_themes.cpp#L135]this set of rules[/url].
+			- [b]Dark[/b] makes fonts and icons dark (suitable for light themes). Icon colors are automatically converted by the editor following the set of rules defined in [url=https://github.com/godotengine/godot/blob/master/editor/editor_themes.cpp]this file[/url].
+			- [b]Light[/b] makes fonts and icons light (suitable for dark themes).
 		</member>
 		</member>
 		<member name="interface/theme/icon_saturation" type="float" setter="" getter="">
 		<member name="interface/theme/icon_saturation" type="float" setter="" getter="">
 			The saturation to use for editor icons. Higher values result in more vibrant colors.
 			The saturation to use for editor icons. Higher values result in more vibrant colors.

+ 6 - 0
doc/classes/NavigationLink2D.xml

@@ -29,6 +29,12 @@
 				Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
 				Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_rid" qualifiers="const">
+			<return type="RID" />
+			<description>
+				Returns the [RID] of this link on the [NavigationServer2D].
+			</description>
+		</method>
 		<method name="set_global_end_position">
 		<method name="set_global_end_position">
 			<return type="void" />
 			<return type="void" />
 			<param index="0" name="position" type="Vector2" />
 			<param index="0" name="position" type="Vector2" />

+ 6 - 0
doc/classes/NavigationLink3D.xml

@@ -29,6 +29,12 @@
 				Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
 				Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="get_rid" qualifiers="const">
+			<return type="RID" />
+			<description>
+				Returns the [RID] of this link on the [NavigationServer3D].
+			</description>
+		</method>
 		<method name="set_global_end_position">
 		<method name="set_global_end_position">
 			<return type="void" />
 			<return type="void" />
 			<param index="0" name="position" type="Vector3" />
 			<param index="0" name="position" type="Vector3" />

+ 8 - 1
doc/classes/NavigationRegion2D.xml

@@ -43,7 +43,14 @@
 				Returns the current navigation map [RID] used by this region.
 				Returns the current navigation map [RID] used by this region.
 			</description>
 			</description>
 		</method>
 		</method>
-		<method name="get_region_rid" qualifiers="const">
+		<method name="get_region_rid" qualifiers="const" is_deprecated="true">
+			<return type="RID" />
+			<description>
+				Returns the [RID] of this region on the [NavigationServer2D].
+				[i]Deprecated.[/i] Use [method get_rid] instead.
+			</description>
+		</method>
+		<method name="get_rid" qualifiers="const">
 			<return type="RID" />
 			<return type="RID" />
 			<description>
 			<description>
 				Returns the [RID] of this region on the [NavigationServer2D]. Combined with [method NavigationServer2D.map_get_closest_point_owner] can be used to identify the [NavigationRegion2D] closest to a point on the merged navigation map.
 				Returns the [RID] of this region on the [NavigationServer2D]. Combined with [method NavigationServer2D.map_get_closest_point_owner] can be used to identify the [NavigationRegion2D] closest to a point on the merged navigation map.

+ 8 - 1
doc/classes/NavigationRegion3D.xml

@@ -36,7 +36,14 @@
 				Returns the current navigation map [RID] used by this region.
 				Returns the current navigation map [RID] used by this region.
 			</description>
 			</description>
 		</method>
 		</method>
-		<method name="get_region_rid" qualifiers="const">
+		<method name="get_region_rid" qualifiers="const" is_deprecated="true">
+			<return type="RID" />
+			<description>
+				Returns the [RID] of this region on the [NavigationServer3D].
+				[i]Deprecated.[/i] Use [method get_rid] instead.
+			</description>
+		</method>
+		<method name="get_rid" qualifiers="const">
 			<return type="RID" />
 			<return type="RID" />
 			<description>
 			<description>
 				Returns the [RID] of this region on the [NavigationServer3D]. Combined with [method NavigationServer3D.map_get_closest_point_owner] can be used to identify the [NavigationRegion3D] closest to a point on the merged navigation map.
 				Returns the [RID] of this region on the [NavigationServer3D]. Combined with [method NavigationServer3D.map_get_closest_point_owner] can be used to identify the [NavigationRegion3D] closest to a point on the merged navigation map.

+ 10 - 6
doc/classes/RenderingServer.xml

@@ -5130,22 +5130,26 @@
 			Uses the default filter mode for this [Viewport].
 			Uses the default filter mode for this [Viewport].
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="1" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="1" enum="CanvasItemTextureFilter">
-			The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized.
+			The texture filter reads from the nearest pixel only. This makes the texture look pixelated from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR" value="2" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR" value="2" enum="CanvasItemTextureFilter">
-			The texture filter blends between the nearest 4 pixels. Use this when you want to avoid a pixelated style, but do not want mipmaps.
+			The texture filter blends between the nearest 4 pixels. This makes the texture look smooth from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="CanvasItemTextureFilter">
-			The texture filter reads from the nearest pixel in the nearest mipmap. The fastest way to read from textures with mipmaps.
+			The texture filter reads from the nearest pixel and blends between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look pixelated from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="4" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="4" enum="CanvasItemTextureFilter">
-			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps.
+			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look smooth from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC" value="5" enum="CanvasItemTextureFilter">
-			The texture filter reads from the nearest pixel, but selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera.
+			The texture filter reads from the nearest pixel and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look pixelated from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="6" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC" value="6" enum="CanvasItemTextureFilter">
-			The texture filter blends between the nearest 4 pixels and selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. This is the slowest of the filtering options, but results in the highest quality texturing.
+			The texture filter blends between the nearest 4 pixels and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look smooth from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_MAX" value="7" enum="CanvasItemTextureFilter">
 		<constant name="CANVAS_ITEM_TEXTURE_FILTER_MAX" value="7" enum="CanvasItemTextureFilter">
 			Max value for [enum CanvasItemTextureFilter] enum.
 			Max value for [enum CanvasItemTextureFilter] enum.

+ 0 - 1
doc/classes/VideoStreamPlayer.xml

@@ -6,7 +6,6 @@
 	<description>
 	<description>
 		A control used for playback of [VideoStream] resources.
 		A control used for playback of [VideoStream] resources.
 		Supported video formats are [url=https://www.theora.org/]Ogg Theora[/url] ([code].ogv[/code], [VideoStreamTheora]) and any format exposed via a GDExtension plugin.
 		Supported video formats are [url=https://www.theora.org/]Ogg Theora[/url] ([code].ogv[/code], [VideoStreamTheora]) and any format exposed via a GDExtension plugin.
-		[b]Note:[/b] Due to a bug, VideoStreamPlayer does not support localization remapping yet.
 		[b]Warning:[/b] On Web, video playback [i]will[/i] perform poorly due to missing architecture-specific assembly optimizations.
 		[b]Warning:[/b] On Web, video playback [i]will[/i] perform poorly due to missing architecture-specific assembly optimizations.
 	</description>
 	</description>
 	<tutorials>
 	<tutorials>

+ 6 - 4
doc/classes/Viewport.xml

@@ -560,16 +560,18 @@
 			Draws the internal resolution buffer of the scene before post-processing is applied.
 			Draws the internal resolution buffer of the scene before post-processing is applied.
 		</constant>
 		</constant>
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="0" enum="DefaultCanvasItemTextureFilter">
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="0" enum="DefaultCanvasItemTextureFilter">
-			The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized.
+			The texture filter reads from the nearest pixel only. This makes the texture look pixelated from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR" value="1" enum="DefaultCanvasItemTextureFilter">
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR" value="1" enum="DefaultCanvasItemTextureFilter">
-			The texture filter blends between the nearest 4 pixels. Use this when you want to avoid a pixelated style, but do not want mipmaps.
+			The texture filter blends between the nearest 4 pixels. This makes the texture look smooth from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="2" enum="DefaultCanvasItemTextureFilter">
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS" value="2" enum="DefaultCanvasItemTextureFilter">
-			The texture filter reads from the nearest pixel in the nearest mipmap. The fastest way to read from textures with mipmaps.
+			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look smooth from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="DefaultCanvasItemTextureFilter">
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS" value="3" enum="DefaultCanvasItemTextureFilter">
-			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps.
+			The texture filter reads from the nearest pixel and blends between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look pixelated from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX" value="4" enum="DefaultCanvasItemTextureFilter">
 		<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_MAX" value="4" enum="DefaultCanvasItemTextureFilter">
 			Max value for [enum DefaultCanvasItemTextureFilter] enum.
 			Max value for [enum DefaultCanvasItemTextureFilter] enum.

+ 10 - 8
doc/classes/VisualShaderNodeTextureParameter.xml

@@ -57,24 +57,26 @@
 			Sample the texture using the filter determined by the node this shader is attached to.
 			Sample the texture using the filter determined by the node this shader is attached to.
 		</constant>
 		</constant>
 		<constant name="FILTER_NEAREST" value="1" enum="TextureFilter">
 		<constant name="FILTER_NEAREST" value="1" enum="TextureFilter">
-			The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized.
+			The texture filter reads from the nearest pixel only. This makes the texture look pixelated from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="FILTER_LINEAR" value="2" enum="TextureFilter">
 		<constant name="FILTER_LINEAR" value="2" enum="TextureFilter">
-			The texture filter blends between the nearest four pixels. Use this for most cases where you want to avoid a pixelated style.
+			The texture filter blends between the nearest 4 pixels. This makes the texture look smooth from up close, and grainy from a distance (due to mipmaps not being sampled).
 		</constant>
 		</constant>
 		<constant name="FILTER_NEAREST_MIPMAP" value="3" enum="TextureFilter">
 		<constant name="FILTER_NEAREST_MIPMAP" value="3" enum="TextureFilter">
-			The texture filter reads from the nearest pixel in the nearest mipmap. This is the fastest way to read from textures with mipmaps.
+			The texture filter reads from the nearest pixel and blends between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look pixelated from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="FILTER_LINEAR_MIPMAP" value="4" enum="TextureFilter">
 		<constant name="FILTER_LINEAR_MIPMAP" value="4" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps. Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
+			The texture filter blends between the nearest 4 pixels and between the nearest 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]). This makes the texture look smooth from up close, and smooth from a distance.
+			Use this for non-pixel art textures that may be viewed at a low scale (e.g. due to [Camera2D] zoom or sprite scaling), as mipmaps are important to smooth out pixels that are smaller than on-screen pixels.
 		</constant>
 		</constant>
 		<constant name="FILTER_NEAREST_MIPMAP_ANISOTROPIC" value="5" enum="TextureFilter">
 		<constant name="FILTER_NEAREST_MIPMAP_ANISOTROPIC" value="5" enum="TextureFilter">
-			The texture filter reads from the nearest pixel, but selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
-			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant FILTER_LINEAR_MIPMAP] is usually more appropriate.
+			The texture filter reads from the nearest pixel and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look pixelated from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant FILTER_NEAREST_MIPMAP] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="FILTER_LINEAR_MIPMAP_ANISOTROPIC" value="6" enum="TextureFilter">
 		<constant name="FILTER_LINEAR_MIPMAP_ANISOTROPIC" value="6" enum="TextureFilter">
-			The texture filter blends between the nearest 4 pixels and selects a mipmap based on the angle between the surface and the camera view. This reduces artifacts on surfaces that are almost in line with the camera. This is the slowest of the filtering options, but results in the highest quality texturing. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
-			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant FILTER_LINEAR_MIPMAP] is usually more appropriate.
+			The texture filter blends between the nearest 4 pixels and blends between 2 mipmaps (or uses the nearest mipmap if [member ProjectSettings.rendering/textures/default_filters/use_nearest_mipmap_filter] is [code]true[/code]) based on the angle between the surface and the camera view. This makes the texture look smooth from up close, and smooth from a distance. Anisotropic filtering improves texture quality on surfaces that are almost in line with the camera, but is slightly slower. The anisotropic filtering level can be changed by adjusting [member ProjectSettings.rendering/textures/default_filters/anisotropic_filtering_level].
+			[b]Note:[/b] This texture filter is rarely useful in 2D projects. [constant FILTER_LINEAR_MIPMAP] is usually more appropriate in this case.
 		</constant>
 		</constant>
 		<constant name="FILTER_MAX" value="7" enum="TextureFilter">
 		<constant name="FILTER_MAX" value="7" enum="TextureFilter">
 			Represents the size of the [enum TextureFilter] enum.
 			Represents the size of the [enum TextureFilter] enum.

+ 11 - 16
doc/tools/make_rst.py

@@ -1361,7 +1361,7 @@ def make_enum(t: str, is_bitfield: bool, state: State) -> str:
         if is_bitfield:
         if is_bitfield:
             if not state.classes[c].enums[e].is_bitfield:
             if not state.classes[c].enums[e].is_bitfield:
                 print_error(f'{state.current_class}.xml: Enum "{t}" is not bitfield.', state)
                 print_error(f'{state.current_class}.xml: Enum "{t}" is not bitfield.', state)
-            return f"|bitfield|\<:ref:`{e}<enum_{c}_{e}>`\>"
+            return f"|bitfield|\\<:ref:`{e}<enum_{c}_{e}>`\\>"
         else:
         else:
             return f":ref:`{e}<enum_{c}_{e}>`"
             return f":ref:`{e}<enum_{c}_{e}>`"
 
 
@@ -1552,16 +1552,11 @@ def make_rst_index(grouped_classes: Dict[str, List[str]], dry_run: bool, output_
 
 
     f.write(".. _doc_class_reference:\n\n")
     f.write(".. _doc_class_reference:\n\n")
 
 
-    main_title = translate("All classes")
-    f.write(f"{main_title}\n")
-    f.write(f"{'=' * len(main_title)}\n\n")
+    f.write(make_heading("All classes", "="))
 
 
     for group_name in CLASS_GROUPS:
     for group_name in CLASS_GROUPS:
         if group_name in grouped_classes:
         if group_name in grouped_classes:
-            group_title = translate(CLASS_GROUPS[group_name])
-
-            f.write(f"{group_title}\n")
-            f.write(f"{'=' * len(group_title)}\n\n")
+            f.write(make_heading(CLASS_GROUPS[group_name], "="))
 
 
             f.write(".. toctree::\n")
             f.write(".. toctree::\n")
             f.write("    :maxdepth: 1\n")
             f.write("    :maxdepth: 1\n")
@@ -2082,9 +2077,9 @@ def format_text_block(
                     post_text = text[endurl_pos + 6 :]
                     post_text = text[endurl_pos + 6 :]
 
 
                     if pre_text and pre_text[-1] not in MARKUP_ALLOWED_PRECEDENT:
                     if pre_text and pre_text[-1] not in MARKUP_ALLOWED_PRECEDENT:
-                        pre_text += "\ "
+                        pre_text += "\\ "
                     if post_text and post_text[0] not in MARKUP_ALLOWED_SUBSEQUENT:
                     if post_text and post_text[0] not in MARKUP_ALLOWED_SUBSEQUENT:
-                        post_text = "\ " + post_text
+                        post_text = "\\ " + post_text
 
 
                     text = pre_text + tag_text + post_text
                     text = pre_text + tag_text + post_text
                     pos = len(pre_text) + len(tag_text)
                     pos = len(pre_text) + len(tag_text)
@@ -2162,9 +2157,9 @@ def format_text_block(
 
 
         # Properly escape things like `[Node]s`
         # Properly escape things like `[Node]s`
         if escape_pre and pre_text and pre_text[-1] not in MARKUP_ALLOWED_PRECEDENT:
         if escape_pre and pre_text and pre_text[-1] not in MARKUP_ALLOWED_PRECEDENT:
-            pre_text += "\ "
+            pre_text += "\\ "
         if escape_post and post_text and post_text[0] not in MARKUP_ALLOWED_SUBSEQUENT:
         if escape_post and post_text and post_text[0] not in MARKUP_ALLOWED_SUBSEQUENT:
-            post_text = "\ " + post_text
+            post_text = "\\ " + post_text
 
 
         next_brac_pos = post_text.find("[", 0)
         next_brac_pos = post_text.find("[", 0)
         iter_pos = 0
         iter_pos = 0
@@ -2172,7 +2167,7 @@ def format_text_block(
             iter_pos = post_text.find("*", iter_pos, next_brac_pos)
             iter_pos = post_text.find("*", iter_pos, next_brac_pos)
             if iter_pos == -1:
             if iter_pos == -1:
                 break
                 break
-            post_text = f"{post_text[:iter_pos]}\*{post_text[iter_pos + 1 :]}"
+            post_text = f"{post_text[:iter_pos]}\\*{post_text[iter_pos + 1 :]}"
             iter_pos += 2
             iter_pos += 2
 
 
         iter_pos = 0
         iter_pos = 0
@@ -2181,7 +2176,7 @@ def format_text_block(
             if iter_pos == -1:
             if iter_pos == -1:
                 break
                 break
             if not post_text[iter_pos + 1].isalnum():  # don't escape within a snake_case word
             if not post_text[iter_pos + 1].isalnum():  # don't escape within a snake_case word
-                post_text = f"{post_text[:iter_pos]}\_{post_text[iter_pos + 1 :]}"
+                post_text = f"{post_text[:iter_pos]}\\_{post_text[iter_pos + 1 :]}"
                 iter_pos += 2
                 iter_pos += 2
             else:
             else:
                 iter_pos += 1
                 iter_pos += 1
@@ -2222,7 +2217,7 @@ def escape_rst(text: str, until_pos: int = -1) -> str:
         pos = text.find("*", pos, until_pos)
         pos = text.find("*", pos, until_pos)
         if pos == -1:
         if pos == -1:
             break
             break
-        text = f"{text[:pos]}\*{text[pos + 1 :]}"
+        text = f"{text[:pos]}\\*{text[pos + 1 :]}"
         pos += 2
         pos += 2
 
 
     # Escape _ character at the end of a word to avoid interpreting it as an inline hyperlink
     # Escape _ character at the end of a word to avoid interpreting it as an inline hyperlink
@@ -2232,7 +2227,7 @@ def escape_rst(text: str, until_pos: int = -1) -> str:
         if pos == -1:
         if pos == -1:
             break
             break
         if not text[pos + 1].isalnum():  # don't escape within a snake_case word
         if not text[pos + 1].isalnum():  # don't escape within a snake_case word
-            text = f"{text[:pos]}\_{text[pos + 1 :]}"
+            text = f"{text[:pos]}\\_{text[pos + 1 :]}"
             pos += 2
             pos += 2
         else:
         else:
             pos += 1
             pos += 1

+ 2 - 0
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -2938,6 +2938,8 @@ void RasterizerSceneGLES3::_render_list_template(RenderListParameters *p_params,
 				}
 				}
 			}
 			}
 
 
+			material_storage->shaders.scene_shader.version_set_uniform(SceneShaderGLES3::MODEL_FLAGS, inst->flags_cache, shader->version, instance_variant, spec_constants);
+
 			// Can be index count or vertex count
 			// Can be index count or vertex count
 			uint32_t count = 0;
 			uint32_t count = 0;
 			if (surf->lod_index > 0) {
 			if (surf->lod_index > 0) {

+ 25 - 6
drivers/gles3/shaders/scene.glsl

@@ -139,6 +139,8 @@ layout(location = 14) in highp vec4 instance_xform2;
 layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw.
 layout(location = 15) in highp uvec4 instance_color_custom_data; // Color packed into xy, Custom data into zw.
 #endif
 #endif
 
 
+#define FLAGS_NON_UNIFORM_SCALE (1 << 4)
+
 layout(std140) uniform GlobalShaderUniformData { //ubo:1
 layout(std140) uniform GlobalShaderUniformData { //ubo:1
 	vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
 	vec4 global_shader_uniforms[MAX_GLOBAL_SHADER_UNIFORMS];
 };
 };
@@ -242,6 +244,8 @@ uniform highp vec3 compressed_aabb_position;
 uniform highp vec3 compressed_aabb_size;
 uniform highp vec3 compressed_aabb_size;
 uniform highp vec4 uv_scale;
 uniform highp vec4 uv_scale;
 
 
+uniform highp uint model_flags;
+
 /* Varyings */
 /* Varyings */
 
 
 out highp vec3 vertex_interp;
 out highp vec3 vertex_interp;
@@ -310,7 +314,14 @@ void main() {
 #ifdef NORMAL_USED
 #ifdef NORMAL_USED
 	vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0);
 	vec3 normal = oct_to_vec3(axis_tangent_attrib.xy * 2.0 - 1.0);
 #endif
 #endif
-	highp mat3 model_normal_matrix = mat3(model_matrix);
+
+	highp mat3 model_normal_matrix;
+
+	if (bool(model_flags & uint(FLAGS_NON_UNIFORM_SCALE))) {
+		model_normal_matrix = transpose(inverse(mat3(model_matrix)));
+	} else {
+		model_normal_matrix = mat3(model_matrix);
+	}
 
 
 #if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
 #if defined(NORMAL_USED) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
 
 
@@ -1600,6 +1611,8 @@ void main() {
 
 
 #if !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT)
 #if !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT)
 
 
+#ifndef SHADOWS_DISABLED
+
 // Orthogonal shadows
 // Orthogonal shadows
 #if !defined(LIGHT_USE_PSSM2) && !defined(LIGHT_USE_PSSM4)
 #if !defined(LIGHT_USE_PSSM2) && !defined(LIGHT_USE_PSSM4)
 	float directional_shadow = sample_shadow(directional_shadow_atlas, directional_shadows[directional_shadow_index].shadow_atlas_pixel_size, shadow_coord);
 	float directional_shadow = sample_shadow(directional_shadow_atlas, directional_shadows[directional_shadow_index].shadow_atlas_pixel_size, shadow_coord);
@@ -1706,6 +1719,9 @@ void main() {
 	directional_shadow = mix(directional_shadow, 1.0, smoothstep(directional_shadows[directional_shadow_index].fade_from, directional_shadows[directional_shadow_index].fade_to, vertex.z));
 	directional_shadow = mix(directional_shadow, 1.0, smoothstep(directional_shadows[directional_shadow_index].fade_from, directional_shadows[directional_shadow_index].fade_to, vertex.z));
 	directional_shadow = mix(1.0, directional_shadow, directional_lights[directional_shadow_index].shadow_opacity);
 	directional_shadow = mix(1.0, directional_shadow, directional_lights[directional_shadow_index].shadow_opacity);
 
 
+#else
+	float directional_shadow = 1.0f;
+#endif // SHADOWS_DISABLED
 	light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, 1.0, albedo, alpha,
 	light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, 1.0, albedo, alpha,
 #ifdef LIGHT_BACKLIGHT_USED
 #ifdef LIGHT_BACKLIGHT_USED
 			backlight,
 			backlight,
@@ -1725,11 +1741,12 @@ void main() {
 #endif // !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT)
 #endif // !defined(ADDITIVE_OMNI) && !defined(ADDITIVE_SPOT)
 
 
 #ifdef ADDITIVE_OMNI
 #ifdef ADDITIVE_OMNI
+	float omni_shadow = 1.0f;
+#ifndef SHADOWS_DISABLED
 	vec3 light_ray = ((positional_shadows[positional_shadow_index].shadow_matrix * vec4(shadow_coord.xyz, 1.0))).xyz;
 	vec3 light_ray = ((positional_shadows[positional_shadow_index].shadow_matrix * vec4(shadow_coord.xyz, 1.0))).xyz;
-
-	float omni_shadow = texture(omni_shadow_texture, vec4(light_ray, length(light_ray) * omni_lights[omni_light_index].inv_radius));
+	omni_shadow = texture(omni_shadow_texture, vec4(light_ray, length(light_ray) * omni_lights[omni_light_index].inv_radius));
 	omni_shadow = mix(1.0, omni_shadow, omni_lights[omni_light_index].shadow_opacity);
 	omni_shadow = mix(1.0, omni_shadow, omni_lights[omni_light_index].shadow_opacity);
-
+#endif // SHADOWS_DISABLED
 	light_process_omni(omni_light_index, vertex, view, normal, f0, roughness, metallic, omni_shadow, albedo, alpha,
 	light_process_omni(omni_light_index, vertex, view, normal, f0, roughness, metallic, omni_shadow, albedo, alpha,
 #ifdef LIGHT_BACKLIGHT_USED
 #ifdef LIGHT_BACKLIGHT_USED
 			backlight,
 			backlight,
@@ -1748,9 +1765,11 @@ void main() {
 #endif // ADDITIVE_OMNI
 #endif // ADDITIVE_OMNI
 
 
 #ifdef ADDITIVE_SPOT
 #ifdef ADDITIVE_SPOT
-	float spot_shadow = sample_shadow(spot_shadow_texture, positional_shadows[positional_shadow_index].shadow_atlas_pixel_size, shadow_coord);
+	float spot_shadow = 1.0f;
+#ifndef SHADOWS_DISABLED
+	spot_shadow = sample_shadow(spot_shadow_texture, positional_shadows[positional_shadow_index].shadow_atlas_pixel_size, shadow_coord);
 	spot_shadow = mix(1.0, spot_shadow, spot_lights[spot_light_index].shadow_opacity);
 	spot_shadow = mix(1.0, spot_shadow, spot_lights[spot_light_index].shadow_opacity);
-
+#endif // SHADOWS_DISABLED
 	light_process_spot(spot_light_index, vertex, view, normal, f0, roughness, metallic, spot_shadow, albedo, alpha,
 	light_process_spot(spot_light_index, vertex, view, normal, f0, roughness, metallic, spot_shadow, albedo, alpha,
 #ifdef LIGHT_BACKLIGHT_USED
 #ifdef LIGHT_BACKLIGHT_USED
 			backlight,
 			backlight,

+ 11 - 11
drivers/gles3/storage/material_storage.cpp

@@ -2968,17 +2968,17 @@ void SceneShaderData::set_code(const String &p_code) {
 	depth_test = DepthTest(depth_testi);
 	depth_test = DepthTest(depth_testi);
 	cull_mode = Cull(cull_modei);
 	cull_mode = Cull(cull_modei);
 
 
-	vertex_input_mask = uint64_t(uses_normal);
-	vertex_input_mask |= uses_tangent << 1;
-	vertex_input_mask |= uses_color << 2;
-	vertex_input_mask |= uses_uv << 3;
-	vertex_input_mask |= uses_uv2 << 4;
-	vertex_input_mask |= uses_custom0 << 5;
-	vertex_input_mask |= uses_custom1 << 6;
-	vertex_input_mask |= uses_custom2 << 7;
-	vertex_input_mask |= uses_custom3 << 8;
-	vertex_input_mask |= uses_bones << 9;
-	vertex_input_mask |= uses_weights << 10;
+	vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
+	vertex_input_mask |= uses_tangent << RS::ARRAY_TANGENT;
+	vertex_input_mask |= uses_color << RS::ARRAY_COLOR;
+	vertex_input_mask |= uses_uv << RS::ARRAY_TEX_UV;
+	vertex_input_mask |= uses_uv2 << RS::ARRAY_TEX_UV2;
+	vertex_input_mask |= uses_custom0 << RS::ARRAY_CUSTOM0;
+	vertex_input_mask |= uses_custom1 << RS::ARRAY_CUSTOM1;
+	vertex_input_mask |= uses_custom2 << RS::ARRAY_CUSTOM2;
+	vertex_input_mask |= uses_custom3 << RS::ARRAY_CUSTOM3;
+	vertex_input_mask |= uses_bones << RS::ARRAY_BONES;
+	vertex_input_mask |= uses_weights << RS::ARRAY_WEIGHTS;
 
 
 	uses_screen_texture = gen_code.uses_screen_texture;
 	uses_screen_texture = gen_code.uses_screen_texture;
 	uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
 	uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;

+ 11 - 12
drivers/gles3/storage/mesh_storage.cpp

@@ -764,14 +764,17 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
 	int skin_stride = 0;
 	int skin_stride = 0;
 
 
 	for (int i = 0; i < RS::ARRAY_INDEX; i++) {
 	for (int i = 0; i < RS::ARRAY_INDEX; i++) {
+		attribs[i].enabled = false;
+		attribs[i].integer = false;
 		if (!(s->format & (1ULL << i))) {
 		if (!(s->format & (1ULL << i))) {
-			attribs[i].enabled = false;
-			attribs[i].integer = false;
 			continue;
 			continue;
 		}
 		}
 
 
-		attribs[i].enabled = true;
-		attribs[i].integer = false;
+		if ((p_input_mask & (1ULL << i))) {
+			// Only enable if it matches input mask.
+			// Iterate over all anyway, so we can calculate stride.
+			attribs[i].enabled = true;
+		}
 
 
 		switch (i) {
 		switch (i) {
 			case RS::ARRAY_VERTEX: {
 			case RS::ARRAY_VERTEX: {
@@ -1108,8 +1111,6 @@ void MeshStorage::_blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uin
 }
 }
 
 
 void MeshStorage::_compute_skeleton(MeshInstance *p_mi, Skeleton *p_sk, uint32_t p_surface) {
 void MeshStorage::_compute_skeleton(MeshInstance *p_mi, Skeleton *p_sk, uint32_t p_surface) {
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
-
 	// Add in the bones and weights.
 	// Add in the bones and weights.
 	glBindBuffer(GL_ARRAY_BUFFER, p_mi->mesh->surfaces[p_surface]->skin_buffer);
 	glBindBuffer(GL_ARRAY_BUFFER, p_mi->mesh->surfaces[p_surface]->skin_buffer);
 
 
@@ -1200,9 +1201,8 @@ void MeshStorage::update_mesh_instances() {
 
 
 				glBindBuffer(GL_ARRAY_BUFFER, 0);
 				glBindBuffer(GL_ARRAY_BUFFER, 0);
 				GLuint vertex_array_gl = 0;
 				GLuint vertex_array_gl = 0;
-				uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
-				mask = ~mask;
-				uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+				uint64_t mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_VERTEX;
+				uint64_t format = mi->mesh->surfaces[i]->format & mask; // Format should only have vertex, normal, tangent (as necessary).
 				mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
 				mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
 				glBindVertexArray(vertex_array_gl);
 				glBindVertexArray(vertex_array_gl);
 				glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[0]);
 				glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mi->surfaces[i].vertex_buffers[0]);
@@ -1315,9 +1315,8 @@ void MeshStorage::update_mesh_instances() {
 				skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization);
 				skeleton_shader.shader.version_set_uniform(SkeletonShaderGLES3::INVERSE_TRANSFORM_OFFSET, inverse_transform[2], skeleton_shader.shader_version, variant, specialization);
 
 
 				GLuint vertex_array_gl = 0;
 				GLuint vertex_array_gl = 0;
-				uint64_t mask = ((1 << 10) - 1) << 3; // Mask from ARRAY_FORMAT_COLOR to ARRAY_FORMAT_INDEX.
-				mask = ~mask;
-				uint64_t format = mi->surfaces[i].format_cache & mask; // Format should only have vertex, normal, tangent (as necessary) + compressions.
+				uint64_t mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_VERTEX;
+				uint64_t format = mi->mesh->surfaces[i]->format & mask; // Format should only have vertex, normal, tangent (as necessary).
 				mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
 				mesh_surface_get_vertex_arrays_and_format(mi->mesh->surfaces[i], format, vertex_array_gl);
 				glBindVertexArray(vertex_array_gl);
 				glBindVertexArray(vertex_array_gl);
 				_compute_skeleton(mi, sk, i);
 				_compute_skeleton(mi, sk, i);

+ 5 - 2
drivers/vulkan/rendering_device_vulkan.cpp

@@ -1365,6 +1365,9 @@ Error RenderingDeviceVulkan::_buffer_allocate(Buffer *p_buffer, uint32_t p_size,
 	allocInfo.memoryTypeBits = 0;
 	allocInfo.memoryTypeBits = 0;
 	allocInfo.pool = nullptr;
 	allocInfo.pool = nullptr;
 	allocInfo.pUserData = nullptr;
 	allocInfo.pUserData = nullptr;
+	if (p_mem_usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST) {
+		allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+	}
 	if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {
 	if (p_size <= SMALL_ALLOCATION_MAX_SIZE) {
 		uint32_t mem_type_index = 0;
 		uint32_t mem_type_index = 0;
 		vmaFindMemoryTypeIndexForBufferInfo(allocator, &bufferInfo, &allocInfo, &mem_type_index);
 		vmaFindMemoryTypeIndexForBufferInfo(allocator, &bufferInfo, &allocInfo, &mem_type_index);
@@ -1410,7 +1413,7 @@ Error RenderingDeviceVulkan::_insert_staging_block() {
 	VmaAllocationCreateInfo allocInfo;
 	VmaAllocationCreateInfo allocInfo;
 	allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
 	allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
 	allocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST;
 	allocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST;
-	allocInfo.requiredFlags = 0;
+	allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
 	allocInfo.preferredFlags = 0;
 	allocInfo.preferredFlags = 0;
 	allocInfo.memoryTypeBits = 0;
 	allocInfo.memoryTypeBits = 0;
 	allocInfo.pool = nullptr;
 	allocInfo.pool = nullptr;
@@ -5995,7 +5998,7 @@ Error RenderingDeviceVulkan::buffer_update(RID p_buffer, uint32_t p_offset, uint
 	// No barrier should be needed here.
 	// No barrier should be needed here.
 	// _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, true);
 	// _buffer_memory_barrier(buffer->buffer, p_offset, p_size, dst_stage_mask, VK_PIPELINE_STAGE_TRANSFER_BIT, dst_access, VK_ACCESS_TRANSFER_WRITE_BIT, true);
 
 
-	Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, p_post_barrier);
+	Error err = _buffer_update(buffer, p_offset, (uint8_t *)p_data, p_size, true);
 	if (err) {
 	if (err) {
 		return err;
 		return err;
 	}
 	}

+ 8 - 3
drivers/vulkan/rendering_device_vulkan.h

@@ -43,7 +43,7 @@
 #define _DEBUG
 #define _DEBUG
 #endif
 #endif
 #endif
 #endif
-#include "vk_mem_alloc.h"
+#include "thirdparty/vulkan/vk_mem_alloc.h"
 
 
 #ifdef USE_VOLK
 #ifdef USE_VOLK
 #include <volk.h>
 #include <volk.h>
@@ -1015,8 +1015,13 @@ class RenderingDeviceVulkan : public RenderingDevice {
 		List<ComputePipeline> compute_pipelines_to_dispose_of;
 		List<ComputePipeline> compute_pipelines_to_dispose_of;
 
 
 		VkCommandPool command_pool = VK_NULL_HANDLE;
 		VkCommandPool command_pool = VK_NULL_HANDLE;
-		VkCommandBuffer setup_command_buffer = VK_NULL_HANDLE; // Used at the beginning of every frame for set-up.
-		VkCommandBuffer draw_command_buffer = VK_NULL_HANDLE; // Used at the beginning of every frame for set-up.
+		// Used for filling up newly created buffers with data provided on creation.
+		// Primarily intended to be accessed by worker threads.
+		// Ideally this cmd buffer should use an async transfer queue.
+		VkCommandBuffer setup_command_buffer = VK_NULL_HANDLE;
+		// The main cmd buffer for drawing and compute.
+		// Primarily intended to be used by the main thread to do most stuff.
+		VkCommandBuffer draw_command_buffer = VK_NULL_HANDLE;
 
 
 		struct Timestamp {
 		struct Timestamp {
 			String description;
 			String description;

+ 19 - 23
editor/editor_about.cpp

@@ -39,29 +39,25 @@
 // The metadata key used to store and retrieve the version text to copy to the clipboard.
 // The metadata key used to store and retrieve the version text to copy to the clipboard.
 const String EditorAbout::META_TEXT_TO_COPY = "text_to_copy";
 const String EditorAbout::META_TEXT_TO_COPY = "text_to_copy";
 
 
-void EditorAbout::_theme_changed() {
-	const Ref<Font> font = get_theme_font(SNAME("source"), EditorStringName(EditorFonts));
-	const int font_size = get_theme_font_size(SNAME("source_size"), EditorStringName(EditorFonts));
-
-	_tpl_text->begin_bulk_theme_override();
-	_tpl_text->add_theme_font_override("normal_font", font);
-	_tpl_text->add_theme_font_size_override("normal_font_size", font_size);
-	_tpl_text->add_theme_constant_override("line_separation", 4 * EDSCALE);
-	_tpl_text->end_bulk_theme_override();
-
-	_license_text->begin_bulk_theme_override();
-	_license_text->add_theme_font_override("normal_font", font);
-	_license_text->add_theme_font_size_override("normal_font_size", font_size);
-	_license_text->add_theme_constant_override("line_separation", 4 * EDSCALE);
-	_license_text->end_bulk_theme_override();
-
-	_logo->set_texture(get_editor_theme_icon(SNAME("Logo")));
-}
-
 void EditorAbout::_notification(int p_what) {
 void EditorAbout::_notification(int p_what) {
 	switch (p_what) {
 	switch (p_what) {
-		case NOTIFICATION_ENTER_TREE: {
-			_theme_changed();
+		case NOTIFICATION_THEME_CHANGED: {
+			const Ref<Font> font = get_theme_font(SNAME("source"), EditorStringName(EditorFonts));
+			const int font_size = get_theme_font_size(SNAME("source_size"), EditorStringName(EditorFonts));
+
+			_tpl_text->begin_bulk_theme_override();
+			_tpl_text->add_theme_font_override("normal_font", font);
+			_tpl_text->add_theme_font_size_override("normal_font_size", font_size);
+			_tpl_text->add_theme_constant_override("line_separation", 4 * EDSCALE);
+			_tpl_text->end_bulk_theme_override();
+
+			_license_text->begin_bulk_theme_override();
+			_license_text->add_theme_font_override("normal_font", font);
+			_license_text->add_theme_font_size_override("normal_font_size", font_size);
+			_license_text->add_theme_constant_override("line_separation", 4 * EDSCALE);
+			_license_text->end_bulk_theme_override();
+
+			_logo->set_texture(get_editor_theme_icon(SNAME("Logo")));
 		} break;
 		} break;
 	}
 	}
 }
 }
@@ -128,12 +124,12 @@ EditorAbout::EditorAbout() {
 	set_hide_on_ok(true);
 	set_hide_on_ok(true);
 
 
 	VBoxContainer *vbc = memnew(VBoxContainer);
 	VBoxContainer *vbc = memnew(VBoxContainer);
-	vbc->connect("theme_changed", callable_mp(this, &EditorAbout::_theme_changed));
+	add_child(vbc);
+
 	HBoxContainer *hbc = memnew(HBoxContainer);
 	HBoxContainer *hbc = memnew(HBoxContainer);
 	hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
 	hbc->set_alignment(BoxContainer::ALIGNMENT_CENTER);
 	hbc->set_alignment(BoxContainer::ALIGNMENT_CENTER);
 	hbc->add_theme_constant_override("separation", 30 * EDSCALE);
 	hbc->add_theme_constant_override("separation", 30 * EDSCALE);
-	add_child(vbc);
 	vbc->add_child(hbc);
 	vbc->add_child(hbc);
 
 
 	_logo = memnew(TextureRect);
 	_logo = memnew(TextureRect);

+ 0 - 2
editor/editor_about.h

@@ -64,8 +64,6 @@ private:
 	RichTextLabel *_tpl_text = nullptr;
 	RichTextLabel *_tpl_text = nullptr;
 	TextureRect *_logo = nullptr;
 	TextureRect *_logo = nullptr;
 
 
-	void _theme_changed();
-
 protected:
 protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();

+ 5 - 6
editor/editor_autoload_settings.cpp

@@ -407,31 +407,30 @@ Node *EditorAutoloadSettings::_create_autoload(const String &p_path) {
 		scn.instantiate();
 		scn.instantiate();
 		scn->set_path(p_path);
 		scn->set_path(p_path);
 		scn->reload_from_file();
 		scn->reload_from_file();
-		ERR_FAIL_COND_V_MSG(!scn.is_valid(), nullptr, vformat("Can't autoload: %s.", p_path));
+		ERR_FAIL_COND_V_MSG(!scn.is_valid(), nullptr, vformat("Failed to create an autoload, can't load from path: %s.", p_path));
 
 
 		if (scn.is_valid()) {
 		if (scn.is_valid()) {
 			n = scn->instantiate();
 			n = scn->instantiate();
 		}
 		}
 	} else {
 	} else {
 		Ref<Resource> res = ResourceLoader::load(p_path);
 		Ref<Resource> res = ResourceLoader::load(p_path);
-		ERR_FAIL_COND_V_MSG(res.is_null(), nullptr, vformat("Can't autoload: %s.", p_path));
+		ERR_FAIL_COND_V_MSG(res.is_null(), nullptr, vformat("Failed to create an autoload, can't load from path: %s.", p_path));
 
 
 		Ref<Script> scr = res;
 		Ref<Script> scr = res;
 		if (scr.is_valid()) {
 		if (scr.is_valid()) {
 			StringName ibt = scr->get_instance_base_type();
 			StringName ibt = scr->get_instance_base_type();
 			bool valid_type = ClassDB::is_parent_class(ibt, "Node");
 			bool valid_type = ClassDB::is_parent_class(ibt, "Node");
-			ERR_FAIL_COND_V_MSG(!valid_type, nullptr, vformat("Script does not inherit from Node: %s.", p_path));
+			ERR_FAIL_COND_V_MSG(!valid_type, nullptr, vformat("Failed to create an autoload, script '%s' does not inherit from 'Node'.", p_path));
 
 
 			Object *obj = ClassDB::instantiate(ibt);
 			Object *obj = ClassDB::instantiate(ibt);
-
-			ERR_FAIL_NULL_V_MSG(obj, nullptr, vformat("Cannot instance script for Autoload, expected 'Node' inheritance, got: %s.", ibt));
+			ERR_FAIL_NULL_V_MSG(obj, nullptr, vformat("Failed to create an autoload, cannot instantiate '%s'.", ibt));
 
 
 			n = Object::cast_to<Node>(obj);
 			n = Object::cast_to<Node>(obj);
 			n->set_script(scr);
 			n->set_script(scr);
 		}
 		}
 	}
 	}
 
 
-	ERR_FAIL_NULL_V_MSG(n, nullptr, vformat("Path in Autoload not a node or script: %s.", p_path));
+	ERR_FAIL_NULL_V_MSG(n, nullptr, vformat("Failed to create an autoload, path is not pointing to a scene or a script: %s.", p_path));
 
 
 	return n;
 	return n;
 }
 }

+ 6 - 7
editor/editor_command_palette.cpp

@@ -129,8 +129,8 @@ void EditorCommandPalette::_update_command_search(const String &search_text) {
 			section->set_text(0, item_name);
 			section->set_text(0, item_name);
 			section->set_selectable(0, false);
 			section->set_selectable(0, false);
 			section->set_selectable(1, false);
 			section->set_selectable(1, false);
-			section->set_custom_bg_color(0, search_options->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
-			section->set_custom_bg_color(1, search_options->get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
+			section->set_custom_bg_color(0, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
+			section->set_custom_bg_color(1, get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor)));
 
 
 			sections[section_name] = section;
 			sections[section_name] = section;
 		}
 		}
@@ -164,6 +164,10 @@ void EditorCommandPalette::_notification(int p_what) {
 				was_showed = true;
 				was_showed = true;
 			}
 			}
 		} break;
 		} break;
+
+		case NOTIFICATION_THEME_CHANGED: {
+			command_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
+		} break;
 	}
 	}
 }
 }
 
 
@@ -303,10 +307,6 @@ Ref<Shortcut> EditorCommandPalette::add_shortcut_command(const String &p_command
 	return p_shortcut;
 	return p_shortcut;
 }
 }
 
 
-void EditorCommandPalette::_theme_changed() {
-	command_search_box->set_right_icon(search_options->get_editor_theme_icon(SNAME("Search")));
-}
-
 void EditorCommandPalette::_save_history() const {
 void EditorCommandPalette::_save_history() const {
 	Dictionary command_history;
 	Dictionary command_history;
 
 
@@ -330,7 +330,6 @@ EditorCommandPalette::EditorCommandPalette() {
 	connect("confirmed", callable_mp(this, &EditorCommandPalette::_confirmed));
 	connect("confirmed", callable_mp(this, &EditorCommandPalette::_confirmed));
 
 
 	VBoxContainer *vbc = memnew(VBoxContainer);
 	VBoxContainer *vbc = memnew(VBoxContainer);
-	vbc->connect("theme_changed", callable_mp(this, &EditorCommandPalette::_theme_changed));
 	add_child(vbc);
 	add_child(vbc);
 
 
 	command_search_box = memnew(LineEdit);
 	command_search_box = memnew(LineEdit);

+ 1 - 2
editor/editor_command_palette.h

@@ -83,10 +83,9 @@ class EditorCommandPalette : public ConfirmationDialog {
 	float _score_path(const String &p_search, const String &p_path);
 	float _score_path(const String &p_search, const String &p_path);
 	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _confirmed();
 	void _confirmed();
-	void _update_command_keys();
 	void _add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text = "None");
 	void _add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text = "None");
-	void _theme_changed();
 	void _save_history() const;
 	void _save_history() const;
+
 	EditorCommandPalette();
 	EditorCommandPalette();
 
 
 protected:
 protected:

+ 3 - 3
editor/editor_node.cpp

@@ -3459,13 +3459,13 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
 		}
 		}
 
 
 		// Plugin init scripts must inherit from EditorPlugin and be tools.
 		// Plugin init scripts must inherit from EditorPlugin and be tools.
-		if (String(scr->get_instance_base_type()) != "EditorPlugin") {
-			show_warning(vformat(TTR("Unable to load addon script from path: '%s' Base type is not EditorPlugin."), script_path));
+		if (!ClassDB::is_parent_class(scr->get_instance_base_type(), "EditorPlugin")) {
+			show_warning(vformat(TTR("Unable to load addon script from path: '%s'. Base type is not 'EditorPlugin'."), script_path));
 			return;
 			return;
 		}
 		}
 
 
 		if (!scr->is_tool()) {
 		if (!scr->is_tool()) {
-			show_warning(vformat(TTR("Unable to load addon script from path: '%s' Script is not in tool mode."), script_path));
+			show_warning(vformat(TTR("Unable to load addon script from path: '%s'. Script is not in tool mode."), script_path));
 			return;
 			return;
 		}
 		}
 	}
 	}

+ 8 - 0
editor/editor_properties_array_dict.cpp

@@ -198,6 +198,10 @@ void EditorPropertyArray::_property_changed(const String &p_property, Variant p_
 		return;
 		return;
 	}
 	}
 
 
+	if (p_value.get_type() == Variant::OBJECT && p_value.is_null()) {
+		p_value = Variant(); // `EditorResourcePicker` resets to `Ref<Resource>()`. See GH-82716.
+	}
+
 	int index;
 	int index;
 	if (p_property.begins_with("metadata/")) {
 	if (p_property.begins_with("metadata/")) {
 		index = p_property.get_slice("/", 2).to_int();
 		index = p_property.get_slice("/", 2).to_int();
@@ -726,6 +730,10 @@ EditorPropertyArray::EditorPropertyArray() {
 ///////////////////// DICTIONARY ///////////////////////////
 ///////////////////// DICTIONARY ///////////////////////////
 
 
 void EditorPropertyDictionary::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
 void EditorPropertyDictionary::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+	if (p_value.get_type() == Variant::OBJECT && p_value.is_null()) {
+		p_value = Variant(); // `EditorResourcePicker` resets to `Ref<Resource>()`. See GH-82716.
+	}
+
 	if (p_property == "new_item_key") {
 	if (p_property == "new_item_key") {
 		object->set_new_item_key(p_value);
 		object->set_new_item_key(p_value);
 	} else if (p_property == "new_item_value") {
 	} else if (p_property == "new_item_value") {

+ 4 - 5
editor/editor_quick_open.cpp

@@ -250,23 +250,22 @@ void EditorQuickOpen::_notification(int p_what) {
 			}
 			}
 		} break;
 		} break;
 
 
+		case NOTIFICATION_THEME_CHANGED: {
+			search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
+		} break;
+
 		case NOTIFICATION_EXIT_TREE: {
 		case NOTIFICATION_EXIT_TREE: {
 			disconnect("confirmed", callable_mp(this, &EditorQuickOpen::_confirmed));
 			disconnect("confirmed", callable_mp(this, &EditorQuickOpen::_confirmed));
 		} break;
 		} break;
 	}
 	}
 }
 }
 
 
-void EditorQuickOpen::_theme_changed() {
-	search_box->set_right_icon(search_options->get_editor_theme_icon(SNAME("Search")));
-}
-
 void EditorQuickOpen::_bind_methods() {
 void EditorQuickOpen::_bind_methods() {
 	ADD_SIGNAL(MethodInfo("quick_open"));
 	ADD_SIGNAL(MethodInfo("quick_open"));
 }
 }
 
 
 EditorQuickOpen::EditorQuickOpen() {
 EditorQuickOpen::EditorQuickOpen() {
 	VBoxContainer *vbc = memnew(VBoxContainer);
 	VBoxContainer *vbc = memnew(VBoxContainer);
-	vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed));
 	add_child(vbc);
 	add_child(vbc);
 
 
 	search_box = memnew(LineEdit);
 	search_box = memnew(LineEdit);

+ 0 - 2
editor/editor_quick_open.h

@@ -72,8 +72,6 @@ class EditorQuickOpen : public ConfirmationDialog {
 	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _sbox_input(const Ref<InputEvent> &p_ie);
 	void _text_changed(const String &p_newtext);
 	void _text_changed(const String &p_newtext);
 
 
-	void _theme_changed();
-
 protected:
 protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();

+ 2 - 2
editor/export/editor_export_platform.cpp

@@ -1431,7 +1431,7 @@ void EditorExportPlatform::zip_folder_recursive(zipFile &p_zip, const String &p_
 					nullptr,
 					nullptr,
 					0,
 					0,
 					0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
 					0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
-					0);
+					1 << 11); // Bit 11 is the language encoding flag. When set, filename and comment fields must be encoded using UTF-8.
 
 
 			String target = da->read_link(f);
 			String target = da->read_link(f);
 			zipWriteInFileInZip(p_zip, target.utf8().get_data(), target.utf8().size());
 			zipWriteInFileInZip(p_zip, target.utf8().get_data(), target.utf8().size());
@@ -1475,7 +1475,7 @@ void EditorExportPlatform::zip_folder_recursive(zipFile &p_zip, const String &p_
 					nullptr,
 					nullptr,
 					0,
 					0,
 					0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
 					0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
-					0);
+					1 << 11); // Bit 11 is the language encoding flag. When set, filename and comment fields must be encoded using UTF-8.
 
 
 			Ref<FileAccess> fa = FileAccess::open(dir.path_join(f), FileAccess::READ);
 			Ref<FileAccess> fa = FileAccess::open(dir.path_join(f), FileAccess::READ);
 			if (fa.is_null()) {
 			if (fa.is_null()) {

+ 6 - 6
editor/export/project_export.cpp

@@ -90,11 +90,6 @@ ProjectExportTextureFormatError::ProjectExportTextureFormatError() {
 	fix_texture_format_button->connect("pressed", callable_mp(this, &ProjectExportTextureFormatError::_on_fix_texture_format_pressed));
 	fix_texture_format_button->connect("pressed", callable_mp(this, &ProjectExportTextureFormatError::_on_fix_texture_format_pressed));
 }
 }
 
 
-void ProjectExportDialog::_theme_changed() {
-	duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
-	delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
-}
-
 void ProjectExportDialog::_notification(int p_what) {
 void ProjectExportDialog::_notification(int p_what) {
 	switch (p_what) {
 	switch (p_what) {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
 		case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -103,6 +98,11 @@ void ProjectExportDialog::_notification(int p_what) {
 			}
 			}
 		} break;
 		} break;
 
 
+		case NOTIFICATION_THEME_CHANGED: {
+			duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
+			delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
+		} break;
+
 		case NOTIFICATION_READY: {
 		case NOTIFICATION_READY: {
 			duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
 			duplicate_preset->set_icon(presets->get_editor_theme_icon(SNAME("Duplicate")));
 			delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
 			delete_preset->set_icon(presets->get_editor_theme_icon(SNAME("Remove")));
@@ -1161,8 +1161,8 @@ ProjectExportDialog::ProjectExportDialog() {
 	set_clamp_to_embedder(true);
 	set_clamp_to_embedder(true);
 
 
 	VBoxContainer *main_vb = memnew(VBoxContainer);
 	VBoxContainer *main_vb = memnew(VBoxContainer);
-	main_vb->connect("theme_changed", callable_mp(this, &ProjectExportDialog::_theme_changed));
 	add_child(main_vb);
 	add_child(main_vb);
+
 	HSplitContainer *hbox = memnew(HSplitContainer);
 	HSplitContainer *hbox = memnew(HSplitContainer);
 	main_vb->add_child(hbox);
 	main_vb->add_child(hbox);
 	hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);

+ 0 - 1
editor/export/project_export.h

@@ -188,7 +188,6 @@ class ProjectExportDialog : public ConfirmationDialog {
 	void _tab_changed(int);
 	void _tab_changed(int);
 
 
 protected:
 protected:
-	void _theme_changed();
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();
 
 

+ 8 - 1
editor/filesystem_dock.cpp

@@ -1595,6 +1595,9 @@ void FileSystemDock::_update_dependencies_after_move(const HashMap<String, Strin
 	// The following code assumes that the following holds:
 	// The following code assumes that the following holds:
 	// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
 	// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
 	// 2) ResourceLoader can use the new paths without needing to call rescan.
 	// 2) ResourceLoader can use the new paths without needing to call rescan.
+
+	// The currently edited scene should be reloaded first, so get it's path (GH-82652).
+	const String &edited_scene_path = EditorNode::get_editor_data().get_scene_path(EditorNode::get_editor_data().get_edited_scene());
 	List<String> scenes_to_reload;
 	List<String> scenes_to_reload;
 	for (const String &E : p_file_owners) {
 	for (const String &E : p_file_owners) {
 		// Because we haven't called a rescan yet the found remap might still be an old path itself.
 		// Because we haven't called a rescan yet the found remap might still be an old path itself.
@@ -1604,7 +1607,11 @@ void FileSystemDock::_update_dependencies_after_move(const HashMap<String, Strin
 		const Error err = ResourceLoader::rename_dependencies(file, p_renames);
 		const Error err = ResourceLoader::rename_dependencies(file, p_renames);
 		if (err == OK) {
 		if (err == OK) {
 			if (ResourceLoader::get_resource_type(file) == "PackedScene") {
 			if (ResourceLoader::get_resource_type(file) == "PackedScene") {
-				scenes_to_reload.push_back(file);
+				if (file == edited_scene_path) {
+					scenes_to_reload.push_front(file);
+				} else {
+					scenes_to_reload.push_back(file);
+				}
 			}
 			}
 		} else {
 		} else {
 			EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies for:") + "\n" + E + "\n");
 			EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies for:") + "\n" + E + "\n");

+ 18 - 7
editor/gui/scene_tree_editor.cpp

@@ -50,7 +50,7 @@
 #include "scene/main/window.h"
 #include "scene/main/window.h"
 #include "scene/resources/packed_scene.h"
 #include "scene/resources/packed_scene.h"
 
 
-Node *SceneTreeEditor::get_scene_node() {
+Node *SceneTreeEditor::get_scene_node() const {
 	ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
 	ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
 
 
 	return get_tree()->get_edited_scene_root();
 	return get_tree()->get_edited_scene_root();
@@ -1218,11 +1218,8 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
 
 
 		Node *n = get_node(np);
 		Node *n = get_node(np);
 		if (n) {
 		if (n) {
-			// Only allow selection if not part of an instantiated scene.
-			if (!n->get_owner() || n->get_owner() == get_scene_node() || n->get_owner()->get_scene_file_path().is_empty()) {
-				selected_nodes.push_back(n);
-				icons.push_back(next->get_icon(0));
-			}
+			selected_nodes.push_back(n);
+			icons.push_back(next->get_icon(0));
 		}
 		}
 		next = tree->get_next_selected(next);
 		next = tree->get_next_selected(next);
 	}
 	}
@@ -1336,7 +1333,21 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
 		}
 		}
 	}
 	}
 
 
-	return String(d["type"]) == "nodes" && filter.is_empty();
+	if (filter.is_empty() && String(d["type"]) == "nodes") {
+		Array nodes = d["nodes"];
+
+		for (int i = 0; i < nodes.size(); i++) {
+			Node *n = get_node(nodes[i]);
+			// Nodes from an instantiated scene can't be rearranged.
+			if (n && n->get_owner() && n->get_owner() != get_scene_node() && !n->get_owner()->get_scene_file_path().is_empty()) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	return false;
 }
 }
 
 
 void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
 void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {

+ 1 - 1
editor/gui/scene_tree_editor.h

@@ -120,7 +120,7 @@ class SceneTreeEditor : public Control {
 	void _set_item_custom_color(TreeItem *p_item, Color p_color);
 	void _set_item_custom_color(TreeItem *p_item, Color p_color);
 
 
 	void _selection_changed();
 	void _selection_changed();
-	Node *get_scene_node();
+	Node *get_scene_node() const;
 
 
 	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
 	Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
 	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
 	bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;

+ 1 - 1
editor/icons/SnapGrid.svg

@@ -1 +1 @@
-<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 0v2H0v1h2v4H0v1h2v4H0v1h2v2h1v-2h3v-1H3V8h4l1-1V3h4v3h1V3h2V2h-2V0h-1v2H8V0H7v2H3V0zm1 3h4v4H3zm4 10v2h2v-2zm6 0v2h2v-2z" fill="#def"/><path d="M7 13h2v-2a2 2 0 0 1 4 0v2h2v-2a4 4 0 0 0-8 0z" fill="#def" fill-opacity=".8"/></svg>
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 0v2H0v1h2v4H0v1h2v4H0v1h2v2h1v-2h3v-1H3V8h4l1-1V3h4v3h1V3h2V2h-2V0h-1v2H8V0H7v2H3V0zm1 3h4v4H3zm4 10v2h2v-2zm6 0v2h2v-2z" fill="#e0e0e0"/><path d="M7 13h2v-2a2 2 0 0 1 4 0v2h2v-2a4 4 0 0 0-8 0z" fill="#e0e0e0" fill-opacity=".8"/></svg>

+ 2 - 0
editor/import/resource_importer_scene.cpp

@@ -1505,6 +1505,7 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
 						new_anim->add_track(anim->track_get_type(j));
 						new_anim->add_track(anim->track_get_type(j));
 						dtrack = new_anim->get_track_count() - 1;
 						dtrack = new_anim->get_track_count() - 1;
 						new_anim->track_set_path(dtrack, anim->track_get_path(j));
 						new_anim->track_set_path(dtrack, anim->track_get_path(j));
+						new_anim->track_set_imported(dtrack, true);
 
 
 						if (kt > (from + 0.01) && k > 0) {
 						if (kt > (from + 0.01) && k > 0) {
 							if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
 							if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
@@ -1580,6 +1581,7 @@ void ResourceImporterScene::_create_slices(AnimationPlayer *ap, Ref<Animation> a
 				new_anim->add_track(anim->track_get_type(j));
 				new_anim->add_track(anim->track_get_type(j));
 				dtrack = new_anim->get_track_count() - 1;
 				dtrack = new_anim->get_track_count() - 1;
 				new_anim->track_set_path(dtrack, anim->track_get_path(j));
 				new_anim->track_set_path(dtrack, anim->track_get_path(j));
+				new_anim->track_set_imported(dtrack, true);
 				if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
 				if (anim->track_get_type(j) == Animation::TYPE_POSITION_3D) {
 					Vector3 p;
 					Vector3 p;
 					anim->try_position_track_interpolate(j, from, &p);
 					anim->try_position_track_interpolate(j, from, &p);

+ 3 - 1
editor/import/resource_importer_wav.cpp

@@ -292,7 +292,9 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
 				loop_end = file->get_32();
 				loop_end = file->get_32();
 			}
 			}
 		}
 		}
-		file->seek(file_pos + chunksize);
+		// Move to the start of the next chunk. Note that RIFF requires a padding byte for odd
+		// chunk sizes.
+		file->seek(file_pos + chunksize + (chunksize & 1));
 	}
 	}
 
 
 	// STEP 2, APPLY CONVERSIONS
 	// STEP 2, APPLY CONVERSIONS

+ 3 - 3
editor/input_event_configuration_dialog.cpp

@@ -553,9 +553,8 @@ void InputEventConfigurationDialog::_notification(int p_what) {
 			event_listener->grab_focus();
 			event_listener->grab_focus();
 		} break;
 		} break;
 
 
-		case NOTIFICATION_ENTER_TREE:
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
-			input_list_search->set_right_icon(input_list_search->get_editor_theme_icon(SNAME("Search")));
+			input_list_search->set_right_icon(get_editor_theme_icon(SNAME("Search")));
 
 
 			key_mode->set_item_icon(KEYMODE_KEYCODE, get_editor_theme_icon(SNAME("Keyboard")));
 			key_mode->set_item_icon(KEYMODE_KEYCODE, get_editor_theme_icon(SNAME("Keyboard")));
 			key_mode->set_item_icon(KEYMODE_PHY_KEYCODE, get_editor_theme_icon(SNAME("KeyboardPhysical")));
 			key_mode->set_item_icon(KEYMODE_PHY_KEYCODE, get_editor_theme_icon(SNAME("KeyboardPhysical")));
@@ -613,12 +612,13 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
 	allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION;
 	allowed_input_types = INPUT_KEY | INPUT_MOUSE_BUTTON | INPUT_JOY_BUTTON | INPUT_JOY_MOTION;
 
 
 	set_title(TTR("Event Configuration"));
 	set_title(TTR("Event Configuration"));
-	set_min_size(Size2i(550 * EDSCALE, 0)); // Min width
+	set_min_size(Size2i(550, 0) * EDSCALE);
 
 
 	VBoxContainer *main_vbox = memnew(VBoxContainer);
 	VBoxContainer *main_vbox = memnew(VBoxContainer);
 	add_child(main_vbox);
 	add_child(main_vbox);
 
 
 	event_as_text = memnew(Label);
 	event_as_text = memnew(Label);
+	event_as_text->set_custom_minimum_size(Size2(500, 0) * EDSCALE);
 	event_as_text->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
 	event_as_text->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
 	event_as_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
 	event_as_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
 	event_as_text->add_theme_font_size_override("font_size", 18 * EDSCALE);
 	event_as_text->add_theme_font_size_override("font_size", 18 * EDSCALE);

+ 3 - 0
editor/plugins/gpu_particles_3d_editor_plugin.cpp

@@ -223,6 +223,9 @@ GPUParticles3DEditorBase::GPUParticles3DEditorBase() {
 	emission_dialog->connect("confirmed", callable_mp(this, &GPUParticles3DEditorBase::_generate_emission_points));
 	emission_dialog->connect("confirmed", callable_mp(this, &GPUParticles3DEditorBase::_generate_emission_points));
 
 
 	emission_tree_dialog = memnew(SceneTreeDialog);
 	emission_tree_dialog = memnew(SceneTreeDialog);
+	Vector<StringName> valid_types;
+	valid_types.push_back("MeshInstance3D");
+	emission_tree_dialog->set_valid_types(valid_types);
 	add_child(emission_tree_dialog);
 	add_child(emission_tree_dialog);
 	emission_tree_dialog->connect("selected", callable_mp(this, &GPUParticles3DEditorBase::_node_selected));
 	emission_tree_dialog->connect("selected", callable_mp(this, &GPUParticles3DEditorBase::_node_selected));
 }
 }

+ 3 - 0
editor/plugins/multimesh_editor_plugin.cpp

@@ -354,6 +354,9 @@ MultiMeshEditor::MultiMeshEditor() {
 
 
 	populate_dialog->get_ok_button()->connect("pressed", callable_mp(this, &MultiMeshEditor::_populate));
 	populate_dialog->get_ok_button()->connect("pressed", callable_mp(this, &MultiMeshEditor::_populate));
 	std = memnew(SceneTreeDialog);
 	std = memnew(SceneTreeDialog);
+	Vector<StringName> valid_types;
+	valid_types.push_back("MeshInstance3D");
+	std->set_valid_types(valid_types);
 	populate_dialog->add_child(std);
 	populate_dialog->add_child(std);
 	std->connect("selected", callable_mp(this, &MultiMeshEditor::_browsed));
 	std->connect("selected", callable_mp(this, &MultiMeshEditor::_browsed));
 
 

+ 6 - 1
editor/plugins/node_3d_editor_plugin.cpp

@@ -4152,6 +4152,7 @@ Node *Node3DEditorViewport::_sanitize_preview_node(Node *p_node) const {
 }
 }
 
 
 void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const {
 void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) const {
+	bool add_preview = false;
 	for (int i = 0; i < files.size(); i++) {
 	for (int i = 0; i < files.size(); i++) {
 		String path = files[i];
 		String path = files[i];
 		Ref<Resource> res = ResourceLoader::load(path);
 		Ref<Resource> res = ResourceLoader::load(path);
@@ -4172,9 +4173,13 @@ void Node3DEditorViewport::_create_preview_node(const Vector<String> &files) con
 					}
 					}
 				}
 				}
 			}
 			}
-			EditorNode::get_singleton()->get_scene_root()->add_child(preview_node);
+			add_preview = true;
 		}
 		}
 	}
 	}
+	if (add_preview) {
+		EditorNode::get_singleton()->get_scene_root()->add_child(preview_node);
+	}
+
 	*preview_bounds = _calculate_spatial_bounds(preview_node);
 	*preview_bounds = _calculate_spatial_bounds(preview_node);
 }
 }
 
 

+ 3 - 0
editor/plugins/path_3d_editor_plugin.cpp

@@ -713,6 +713,9 @@ void Path3DEditorPlugin::_notification(int p_what) {
 		} break;
 		} break;
 
 
 		case NOTIFICATION_READY: {
 		case NOTIFICATION_READY: {
+			// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
+			// The toolbar should be extracted to a dedicated control and theme updates should be handled through
+			// the notification.
 			Node3DEditor::get_singleton()->connect("theme_changed", callable_mp(this, &Path3DEditorPlugin::_update_theme));
 			Node3DEditor::get_singleton()->connect("theme_changed", callable_mp(this, &Path3DEditorPlugin::_update_theme));
 		} break;
 		} break;
 	}
 	}

+ 44 - 9
editor/plugins/polygon_2d_editor_plugin.cpp

@@ -456,6 +456,7 @@ void Polygon2DEditor::_uv_mode(int p_mode) {
 	for (int i = 0; i < UV_MODE_MAX; i++) {
 	for (int i = 0; i < UV_MODE_MAX; i++) {
 		uv_button[i]->set_pressed(p_mode == i);
 		uv_button[i]->set_pressed(p_mode == i);
 	}
 	}
+	uv_edit_draw->queue_redraw();
 }
 }
 
 
 void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
 void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
@@ -989,9 +990,36 @@ void Polygon2DEditor::_uv_draw() {
 	mtx.columns[2] = -uv_draw_ofs;
 	mtx.columns[2] = -uv_draw_ofs;
 	mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
 	mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
 
 
-	RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx);
-	uv_edit_draw->draw_texture(base_tex, Point2());
-	RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D());
+	// Draw texture as a background if editing uvs or no uv mapping exist.
+	if (uv_edit_mode[0]->is_pressed() || uv_mode == UV_MODE_CREATE || node->get_polygon().is_empty() || node->get_uv().size() != node->get_polygon().size()) {
+		Transform2D texture_transform = Transform2D(node->get_texture_rotation(), node->get_texture_offset());
+		texture_transform.scale(node->get_texture_scale());
+		texture_transform.affine_invert();
+		RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx * texture_transform);
+		uv_edit_draw->draw_texture(base_tex, Point2());
+		RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D());
+		preview_polygon->hide();
+	} else {
+		preview_polygon->set_transform(mtx);
+		// Keep in sync with newly added Polygon2D properties (when relevant).
+		preview_polygon->set_texture(node->get_texture());
+		preview_polygon->set_texture_offset(node->get_texture_offset());
+		preview_polygon->set_texture_rotation(node->get_texture_rotation());
+		preview_polygon->set_texture_scale(node->get_texture_scale());
+		preview_polygon->set_texture_filter(node->get_texture_filter_in_tree());
+		preview_polygon->set_texture_repeat(node->get_texture_repeat_in_tree());
+		preview_polygon->set_polygon(node->get_polygon());
+		preview_polygon->set_uv(node->get_uv());
+		preview_polygon->set_invert(node->get_invert());
+		preview_polygon->set_invert_border(node->get_invert_border());
+		preview_polygon->set_internal_vertex_count(node->get_internal_vertex_count());
+		if (uv_mode == UV_MODE_ADD_POLYGON) {
+			preview_polygon->set_polygons(Array());
+		} else {
+			preview_polygon->set_polygons(node->get_polygons());
+		}
+		preview_polygon->show();
+	}
 
 
 	if (snap_show_grid) {
 	if (snap_show_grid) {
 		Color grid_color = Color(1.0, 1.0, 1.0, 0.15);
 		Color grid_color = Color(1.0, 1.0, 1.0, 0.15);
@@ -1357,10 +1385,19 @@ Polygon2DEditor::Polygon2DEditor() {
 	HSplitContainer *uv_main_hsc = memnew(HSplitContainer);
 	HSplitContainer *uv_main_hsc = memnew(HSplitContainer);
 	uv_main_vb->add_child(uv_main_hsc);
 	uv_main_vb->add_child(uv_main_hsc);
 	uv_main_hsc->set_v_size_flags(SIZE_EXPAND_FILL);
 	uv_main_hsc->set_v_size_flags(SIZE_EXPAND_FILL);
-	uv_edit_draw = memnew(Panel);
-	uv_main_hsc->add_child(uv_edit_draw);
-	uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
-	uv_edit_draw->set_custom_minimum_size(Size2(200, 200) * EDSCALE);
+
+	uv_edit_background = memnew(Panel);
+	uv_main_hsc->add_child(uv_edit_background);
+	uv_edit_background->set_h_size_flags(SIZE_EXPAND_FILL);
+	uv_edit_background->set_custom_minimum_size(Size2(200, 200) * EDSCALE);
+	uv_edit_background->set_clip_contents(true);
+
+	preview_polygon = memnew(Polygon2D);
+	uv_edit_background->add_child(preview_polygon);
+
+	uv_edit_draw = memnew(Control);
+	uv_edit_background->add_child(uv_edit_draw);
+	uv_edit_draw->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
 
 
 	Control *space = memnew(Control);
 	Control *space = memnew(Control);
 	uv_mode_hb->add_child(space);
 	uv_mode_hb->add_child(space);
@@ -1503,8 +1540,6 @@ Polygon2DEditor::Polygon2DEditor() {
 
 
 	error = memnew(AcceptDialog);
 	error = memnew(AcceptDialog);
 	add_child(error);
 	add_child(error);
-
-	uv_edit_draw->set_clip_contents(true);
 }
 }
 
 
 Polygon2DEditorPlugin::Polygon2DEditorPlugin() :
 Polygon2DEditorPlugin::Polygon2DEditorPlugin() :

+ 3 - 1
editor/plugins/polygon_2d_editor_plugin.h

@@ -82,7 +82,9 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
 	Button *uv_button[UV_MODE_MAX];
 	Button *uv_button[UV_MODE_MAX];
 	Button *b_snap_enable = nullptr;
 	Button *b_snap_enable = nullptr;
 	Button *b_snap_grid = nullptr;
 	Button *b_snap_grid = nullptr;
-	Panel *uv_edit_draw = nullptr;
+	Panel *uv_edit_background = nullptr;
+	Polygon2D *preview_polygon = nullptr;
+	Control *uv_edit_draw = nullptr;
 	HSlider *uv_zoom = nullptr;
 	HSlider *uv_zoom = nullptr;
 	SpinBox *uv_zoom_value = nullptr;
 	SpinBox *uv_zoom_value = nullptr;
 	HScrollBar *uv_hscroll = nullptr;
 	HScrollBar *uv_hscroll = nullptr;

+ 1 - 1
editor/plugins/script_text_editor.cpp

@@ -1650,7 +1650,7 @@ void ScriptTextEditor::reload(bool p_soft) {
 		return;
 		return;
 	}
 	}
 	scr->set_source_code(te->get_text());
 	scr->set_source_code(te->get_text());
-	bool soft = p_soft || scr->get_instance_base_type() == "EditorPlugin"; // Always soft-reload editor plugins.
+	bool soft = p_soft || ClassDB::is_parent_class(scr->get_instance_base_type(), "EditorPlugin"); // Always soft-reload editor plugins.
 
 
 	scr->get_language()->reload_tool_script(scr, soft);
 	scr->get_language()->reload_tool_script(scr, soft);
 }
 }

+ 6 - 2
editor/plugins/tiles/tile_map_editor.cpp

@@ -2373,7 +2373,9 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
 
 
 	// --- Bottom panel tiles ---
 	// --- Bottom panel tiles ---
 	tiles_bottom_panel = memnew(VBoxContainer);
 	tiles_bottom_panel = memnew(VBoxContainer);
-	tiles_bottom_panel->connect("tree_entered", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
+	// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
+	// The toolbar should be extracted to a dedicated control and theme updates should be handled through
+	// the notification.
 	tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
 	tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme));
 	tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging));
 	tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging));
 	tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
 	tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed));
@@ -3536,7 +3538,9 @@ void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_la
 
 
 TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
 TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() {
 	main_vbox_container = memnew(VBoxContainer);
 	main_vbox_container = memnew(VBoxContainer);
-	main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
+	// FIXME: This can trigger theme updates when the nodes that we want to update are not yet available.
+	// The toolbar should be extracted to a dedicated control and theme updates should be handled through
+	// the notification.
 	main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
 	main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme));
 	main_vbox_container->set_name(TTR("Terrains"));
 	main_vbox_container->set_name(TTR("Terrains"));
 
 

+ 1 - 6
editor/project_manager.cpp

@@ -101,12 +101,6 @@ void ProjectDialog::_set_message(const String &p_msg, MessageType p_type, InputT
 	} else if (current_install_icon != new_icon && input_type == INSTALL_PATH) {
 	} else if (current_install_icon != new_icon && input_type == INSTALL_PATH) {
 		install_status_rect->set_texture(new_icon);
 		install_status_rect->set_texture(new_icon);
 	}
 	}
-
-	Size2i window_size = get_size();
-	Size2 contents_min_size = get_contents_minimum_size();
-	if (window_size.x < contents_min_size.x || window_size.y < contents_min_size.y) {
-		set_size(window_size.max(contents_min_size));
-	}
 }
 }
 
 
 String ProjectDialog::_test_path() {
 String ProjectDialog::_test_path() {
@@ -868,6 +862,7 @@ ProjectDialog::ProjectDialog() {
 
 
 	msg = memnew(Label);
 	msg = memnew(Label);
 	msg->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
 	msg->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+	msg->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
 	vb->add_child(msg);
 	vb->add_child(msg);
 
 
 	// Renderer selection.
 	// Renderer selection.

+ 6 - 1
editor/scene_tree_dock.cpp

@@ -2179,6 +2179,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
 		}
 		}
 
 
 		int child_pos = node->get_index(false);
 		int child_pos = node->get_index(false);
+		bool reparented_to_container = Object::cast_to<Container>(new_parent) && Object::cast_to<Control>(node);
 
 
 		undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
 		undo_redo->add_undo_method(node->get_parent(), "add_child", node, true);
 		undo_redo->add_undo_method(node->get_parent(), "move_child", node, child_pos);
 		undo_redo->add_undo_method(node->get_parent(), "move_child", node, child_pos);
@@ -2194,10 +2195,14 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
 			if (Object::cast_to<Node3D>(node)) {
 			if (Object::cast_to<Node3D>(node)) {
 				undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node3D>(node)->get_transform());
 				undo_redo->add_undo_method(node, "set_transform", Object::cast_to<Node3D>(node)->get_transform());
 			}
 			}
-			if (Object::cast_to<Control>(node)) {
+			if (!reparented_to_container && Object::cast_to<Control>(node)) {
 				undo_redo->add_undo_method(node, "set_position", Object::cast_to<Control>(node)->get_position());
 				undo_redo->add_undo_method(node, "set_position", Object::cast_to<Control>(node)->get_position());
 			}
 			}
 		}
 		}
+
+		if (reparented_to_container) {
+			undo_redo->add_undo_method(node, "_edit_set_state", Object::cast_to<Control>(node)->_edit_get_state());
+		}
 	}
 	}
 
 
 	perform_node_renames(nullptr, &path_renames);
 	perform_node_renames(nullptr, &path_renames);

+ 15 - 26
editor/shader_create_dialog.cpp

@@ -48,8 +48,6 @@ enum ShaderType {
 void ShaderCreateDialog::_notification(int p_what) {
 void ShaderCreateDialog::_notification(int p_what) {
 	switch (p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
-			_update_theme();
-
 			String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", "");
 			String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", "");
 			if (!last_lang.is_empty()) {
 			if (!last_lang.is_empty()) {
 				for (int i = 0; i < type_menu->get_item_count(); i++) {
 				for (int i = 0; i < type_menu->get_item_count(); i++) {
@@ -68,28 +66,17 @@ void ShaderCreateDialog::_notification(int p_what) {
 		} break;
 		} break;
 
 
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
-			_update_theme();
-		} break;
-	}
-}
-
-void ShaderCreateDialog::_update_theme() {
-	Ref<Texture2D> shader_icon = gc->get_editor_theme_icon(SNAME("Shader"));
-	if (shader_icon.is_valid()) {
-		type_menu->set_item_icon(0, shader_icon);
-	}
-
-	Ref<Texture2D> visual_shader_icon = gc->get_editor_theme_icon(SNAME("VisualShader"));
-	if (visual_shader_icon.is_valid()) {
-		type_menu->set_item_icon(1, visual_shader_icon);
-	}
+			static const char *shader_types[3] = { "Shader", "VisualShader", "TextFile" };
+			for (int i = 0; i < 3; i++) {
+				Ref<Texture2D> icon = get_editor_theme_icon(shader_types[i]);
+				if (icon.is_valid()) {
+					type_menu->set_item_icon(i, icon);
+				}
+			}
 
 
-	Ref<Texture2D> include_icon = gc->get_editor_theme_icon(SNAME("TextFile"));
-	if (include_icon.is_valid()) {
-		type_menu->set_item_icon(2, include_icon);
+			path_button->set_icon(get_editor_theme_icon(SNAME("Folder")));
+		} break;
 	}
 	}
-
-	path_button->set_icon(get_editor_theme_icon(SNAME("Folder")));
 }
 }
 
 
 void ShaderCreateDialog::_update_language_info() {
 void ShaderCreateDialog::_update_language_info() {
@@ -175,9 +162,10 @@ void fragment() {
 	// Called for every pixel the material is visible on.
 	// Called for every pixel the material is visible on.
 }
 }
 
 
-void light() {
+//void light() {
 	// Called for every pixel for every light affecting the material.
 	// Called for every pixel for every light affecting the material.
-}
+	// Uncomment to replace the default light processing function with this one.
+//}
 )";
 )";
 						break;
 						break;
 					case Shader::MODE_CANVAS_ITEM:
 					case Shader::MODE_CANVAS_ITEM:
@@ -190,9 +178,10 @@ void fragment() {
 	// Called for every pixel the material is visible on.
 	// Called for every pixel the material is visible on.
 }
 }
 
 
-void light() {
+//void light() {
 	// Called for every pixel for every light affecting the CanvasItem.
 	// Called for every pixel for every light affecting the CanvasItem.
-}
+	// Uncomment to replace the default light processing function with this one.
+//}
 )";
 )";
 						break;
 						break;
 					case Shader::MODE_PARTICLES:
 					case Shader::MODE_PARTICLES:

+ 0 - 1
editor/shader_create_dialog.h

@@ -101,7 +101,6 @@ class ShaderCreateDialog : public ConfirmationDialog {
 	void _update_dialog();
 	void _update_dialog();
 
 
 protected:
 protected:
-	void _update_theme();
 	void _notification(int p_what);
 	void _notification(int p_what);
 	static void _bind_methods();
 	static void _bind_methods();
 
 

+ 6 - 8
main/main.cpp

@@ -1758,7 +1758,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 #endif
 #endif
 
 
 		String default_driver = driver_hints.get_slice(",", 0);
 		String default_driver = driver_hints.get_slice(",", 0);
-		String default_driver_macos = driver_hints_angle.get_slice(",", 1);
 
 
 		GLOBAL_DEF_RST_NOVAL("rendering/gl_compatibility/driver", default_driver);
 		GLOBAL_DEF_RST_NOVAL("rendering/gl_compatibility/driver", default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
@@ -1766,7 +1765,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
 		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
-		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver_macos);
+		GLOBAL_DEF_RST_NOVAL(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
 
 
 		GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true);
 		GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true);
 		GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true);
 		GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true);
@@ -3192,31 +3191,30 @@ bool Main::start() {
 						scn.instantiate();
 						scn.instantiate();
 						scn->set_path(info.path);
 						scn->set_path(info.path);
 						scn->reload_from_file();
 						scn->reload_from_file();
-						ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Can't autoload: %s.", info.path));
+						ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
 
 
 						if (scn.is_valid()) {
 						if (scn.is_valid()) {
 							n = scn->instantiate();
 							n = scn->instantiate();
 						}
 						}
 					} else {
 					} else {
 						Ref<Resource> res = ResourceLoader::load(info.path);
 						Ref<Resource> res = ResourceLoader::load(info.path);
-						ERR_CONTINUE_MSG(res.is_null(), vformat("Can't autoload: %s.", info.path));
+						ERR_CONTINUE_MSG(res.is_null(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
 
 
 						Ref<Script> script_res = res;
 						Ref<Script> script_res = res;
 						if (script_res.is_valid()) {
 						if (script_res.is_valid()) {
 							StringName ibt = script_res->get_instance_base_type();
 							StringName ibt = script_res->get_instance_base_type();
 							bool valid_type = ClassDB::is_parent_class(ibt, "Node");
 							bool valid_type = ClassDB::is_parent_class(ibt, "Node");
-							ERR_CONTINUE_MSG(!valid_type, vformat("Script does not inherit from Node: %s.", info.path));
+							ERR_CONTINUE_MSG(!valid_type, vformat("Failed to instantiate an autoload, script '%s' does not inherit from 'Node'.", info.path));
 
 
 							Object *obj = ClassDB::instantiate(ibt);
 							Object *obj = ClassDB::instantiate(ibt);
-
-							ERR_CONTINUE_MSG(!obj, vformat("Cannot instance script for autoload, expected 'Node' inheritance, got: %s."));
+							ERR_CONTINUE_MSG(!obj, vformat("Failed to instantiate an autoload, cannot instantiate '%s'.", ibt));
 
 
 							n = Object::cast_to<Node>(obj);
 							n = Object::cast_to<Node>(obj);
 							n->set_script(script_res);
 							n->set_script(script_res);
 						}
 						}
 					}
 					}
 
 
-					ERR_CONTINUE_MSG(!n, vformat("Path in autoload not a node or script: %s.", info.path));
+					ERR_CONTINUE_MSG(!n, vformat("Failed to instantiate an autoload, path is not pointing to a scene or a script: %s.", info.path));
 					n->set_name(info.name);
 					n->set_name(info.name);
 
 
 					//defer so references are all valid on _ready()
 					//defer so references are all valid on _ready()

+ 10 - 3
methods.py

@@ -907,9 +907,16 @@ def generate_vs_project(env, original_args, project_name="godot"):
                 defines=mono_defines,
                 defines=mono_defines,
             )
             )
 
 
-        env["MSVSBUILDCOM"] = module_configs.build_commandline("scons")
-        env["MSVSREBUILDCOM"] = module_configs.build_commandline("scons vsproj=yes")
-        env["MSVSCLEANCOM"] = module_configs.build_commandline("scons --clean")
+        scons_cmd = "scons"
+
+        path_to_venv = os.getenv("VIRTUAL_ENV")
+        path_to_scons_exe = Path(str(path_to_venv)) / "Scripts" / "scons.exe"
+        if path_to_venv and path_to_scons_exe.exists():
+            scons_cmd = str(path_to_scons_exe)
+
+        env["MSVSBUILDCOM"] = module_configs.build_commandline(scons_cmd)
+        env["MSVSREBUILDCOM"] = module_configs.build_commandline(f"{scons_cmd} vsproj=yes")
+        env["MSVSCLEANCOM"] = module_configs.build_commandline(f"{scons_cmd} --clean")
         if not env.get("MSVS"):
         if not env.get("MSVS"):
             env["MSVS"]["PROJECTSUFFIX"] = ".vcxproj"
             env["MSVS"]["PROJECTSUFFIX"] = ".vcxproj"
             env["MSVS"]["SOLUTIONSUFFIX"] = ".sln"
             env["MSVS"]["SOLUTIONSUFFIX"] = ".sln"

+ 1 - 1
modules/csg/csg_shape.cpp

@@ -2226,7 +2226,7 @@ void CSGPolygon3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "path_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Path3D"), "set_path_node", "get_path_node");
 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "path_node", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Path3D"), "set_path_node", "get_path_node");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "path_interval_type", PROPERTY_HINT_ENUM, "Distance,Subdivide"), "set_path_interval_type", "get_path_interval_type");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "path_interval_type", PROPERTY_HINT_ENUM, "Distance,Subdivide"), "set_path_interval_type", "get_path_interval_type");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_interval", PROPERTY_HINT_RANGE, "0.01,1.0,0.01,exp,or_greater"), "set_path_interval", "get_path_interval");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_interval", PROPERTY_HINT_RANGE, "0.01,1.0,0.01,exp,or_greater"), "set_path_interval", "get_path_interval");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_simplify_angle", PROPERTY_HINT_RANGE, "0.0,180.0,0.1,exp"), "set_path_simplify_angle", "get_path_simplify_angle");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_simplify_angle", PROPERTY_HINT_RANGE, "0.0,180.0,0.1"), "set_path_simplify_angle", "get_path_simplify_angle");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "path_rotation", PROPERTY_HINT_ENUM, "Polygon,Path,PathFollow"), "set_path_rotation", "get_path_rotation");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_local"), "set_path_local", "is_path_local");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_local"), "set_path_local", "is_path_local");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_continuous_u"), "set_path_continuous_u", "is_path_continuous_u");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "path_continuous_u"), "set_path_continuous_u", "is_path_continuous_u");

+ 13 - 0
modules/gdscript/gdscript.cpp

@@ -2329,6 +2329,19 @@ void GDScriptLanguage::reload_all_scripts() {
 			}
 			}
 			elem = elem->next();
 			elem = elem->next();
 		}
 		}
+
+#ifdef TOOLS_ENABLED
+		if (Engine::get_singleton()->is_editor_hint()) {
+			// Reload all pointers to existing singletons so that tool scripts can work with the reloaded extensions.
+			List<Engine::Singleton> singletons;
+			Engine::get_singleton()->get_singletons(&singletons);
+			for (const Engine::Singleton &E : singletons) {
+				if (globals.has(E.name)) {
+					_add_global(E.name, E.ptr);
+				}
+			}
+		}
+#endif
 	}
 	}
 
 
 	//as scripts are going to be reloaded, must proceed without locking here
 	//as scripts are going to be reloaded, must proceed without locking here

+ 26 - 3
modules/gdscript/gdscript_editor.cpp

@@ -1083,6 +1083,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 							List<PropertyInfo> members;
 							List<PropertyInfo> members;
 							scr->get_script_property_list(&members);
 							scr->get_script_property_list(&members);
 							for (const PropertyInfo &E : members) {
 							for (const PropertyInfo &E : members) {
+								if (E.usage & (PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP)) {
+									continue;
+								}
+								if (E.name.contains("/")) {
+									continue;
+								}
 								int location = p_recursion_depth + _get_property_location(scr->get_class_name(), E.name);
 								int location = p_recursion_depth + _get_property_location(scr->get_class_name(), E.name);
 								ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
 								ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
 								r_result.insert(option.display, option);
 								r_result.insert(option.display, option);
@@ -1152,7 +1158,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 						List<PropertyInfo> pinfo;
 						List<PropertyInfo> pinfo;
 						ClassDB::get_property_list(type, &pinfo);
 						ClassDB::get_property_list(type, &pinfo);
 						for (const PropertyInfo &E : pinfo) {
 						for (const PropertyInfo &E : pinfo) {
-							if (E.usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) {
+							if (E.usage & (PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP)) {
 								continue;
 								continue;
 							}
 							}
 							if (E.name.contains("/")) {
 							if (E.name.contains("/")) {
@@ -1213,6 +1219,9 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
 					}
 					}
 
 
 					for (const PropertyInfo &E : members) {
 					for (const PropertyInfo &E : members) {
+						if (E.usage & (PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP)) {
+							continue;
+						}
 						if (!String(E.name).contains("/")) {
 						if (!String(E.name).contains("/")) {
 							ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
 							ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
 							if (GDScriptParser::theme_color_names.has(E.name)) {
 							if (GDScriptParser::theme_color_names.has(E.name)) {
@@ -2667,6 +2676,11 @@ static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, co
 	if (p_context.base == nullptr) {
 	if (p_context.base == nullptr) {
 		return false;
 		return false;
 	}
 	}
+	if (p_subscript->base->datatype.type_source == GDScriptParser::DataType::ANNOTATED_EXPLICIT) {
+		// Annotated type takes precedence.
+		return false;
+	}
+
 	const GDScriptParser::GetNodeNode *get_node = nullptr;
 	const GDScriptParser::GetNodeNode *get_node = nullptr;
 
 
 	switch (p_subscript->base->type) {
 	switch (p_subscript->base->type) {
@@ -2715,10 +2729,19 @@ static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, co
 			if (r_base != nullptr) {
 			if (r_base != nullptr) {
 				*r_base = node;
 				*r_base = node;
 			}
 			}
-			r_base_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
-			r_base_type.kind = GDScriptParser::DataType::NATIVE;
+
+			r_base_type.type_source = GDScriptParser::DataType::INFERRED;
 			r_base_type.builtin_type = Variant::OBJECT;
 			r_base_type.builtin_type = Variant::OBJECT;
 			r_base_type.native_type = node->get_class_name();
 			r_base_type.native_type = node->get_class_name();
+
+			Ref<Script> scr = node->get_script();
+			if (scr.is_null()) {
+				r_base_type.kind = GDScriptParser::DataType::NATIVE;
+			} else {
+				r_base_type.kind = GDScriptParser::DataType::SCRIPT;
+				r_base_type.script_type = scr;
+			}
+
 			return true;
 			return true;
 		}
 		}
 	}
 	}

+ 5 - 6
modules/gdscript/tests/gdscript_test_runner.cpp

@@ -78,31 +78,30 @@ void init_autoloads() {
 			scn.instantiate();
 			scn.instantiate();
 			scn->set_path(info.path);
 			scn->set_path(info.path);
 			scn->reload_from_file();
 			scn->reload_from_file();
-			ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Can't autoload: %s.", info.path));
+			ERR_CONTINUE_MSG(!scn.is_valid(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
 
 
 			if (scn.is_valid()) {
 			if (scn.is_valid()) {
 				n = scn->instantiate();
 				n = scn->instantiate();
 			}
 			}
 		} else {
 		} else {
 			Ref<Resource> res = ResourceLoader::load(info.path);
 			Ref<Resource> res = ResourceLoader::load(info.path);
-			ERR_CONTINUE_MSG(res.is_null(), vformat("Can't autoload: %s.", info.path));
+			ERR_CONTINUE_MSG(res.is_null(), vformat("Failed to instantiate an autoload, can't load from path: %s.", info.path));
 
 
 			Ref<Script> scr = res;
 			Ref<Script> scr = res;
 			if (scr.is_valid()) {
 			if (scr.is_valid()) {
 				StringName ibt = scr->get_instance_base_type();
 				StringName ibt = scr->get_instance_base_type();
 				bool valid_type = ClassDB::is_parent_class(ibt, "Node");
 				bool valid_type = ClassDB::is_parent_class(ibt, "Node");
-				ERR_CONTINUE_MSG(!valid_type, vformat("Script does not inherit from Node: %s.", info.path));
+				ERR_CONTINUE_MSG(!valid_type, vformat("Failed to instantiate an autoload, script '%s' does not inherit from 'Node'.", info.path));
 
 
 				Object *obj = ClassDB::instantiate(ibt);
 				Object *obj = ClassDB::instantiate(ibt);
-
-				ERR_CONTINUE_MSG(!obj, vformat("Cannot instance script for Autoload, expected 'Node' inheritance, got: %s.", ibt));
+				ERR_CONTINUE_MSG(!obj, vformat("Failed to instantiate an autoload, cannot instantiate '%s'.", ibt));
 
 
 				n = Object::cast_to<Node>(obj);
 				n = Object::cast_to<Node>(obj);
 				n->set_script(scr);
 				n->set_script(scr);
 			}
 			}
 		}
 		}
 
 
-		ERR_CONTINUE_MSG(!n, vformat("Path in autoload not a node or script: %s.", info.path));
+		ERR_CONTINUE_MSG(!n, vformat("Failed to instantiate an autoload, path is not pointing to a scene or a script: %s.", info.path));
 		n->set_name(info.name);
 		n->set_name(info.name);
 
 
 		for (int i = 0; i < ScriptServer::get_language_count(); i++) {
 		for (int i = 0; i < ScriptServer::get_language_count(); i++) {

+ 12 - 1
modules/navigation/nav_map.cpp

@@ -1107,8 +1107,14 @@ void NavMap::_update_rvo_obstacles_tree_2d() {
 		obstacle_vertex_count += obstacle->get_vertices().size();
 		obstacle_vertex_count += obstacle->get_vertices().size();
 	}
 	}
 
 
+	// Cleaning old obstacles.
+	for (size_t i = 0; i < rvo_simulation_2d.obstacles_.size(); ++i) {
+		delete rvo_simulation_2d.obstacles_[i];
+	}
+	rvo_simulation_2d.obstacles_.clear();
+
 	// Cannot use LocalVector here as RVO library expects std::vector to build KdTree
 	// Cannot use LocalVector here as RVO library expects std::vector to build KdTree
-	std::vector<RVO2D::Obstacle2D *> raw_obstacles;
+	std::vector<RVO2D::Obstacle2D *> &raw_obstacles = rvo_simulation_2d.obstacles_;
 	raw_obstacles.reserve(obstacle_vertex_count);
 	raw_obstacles.reserve(obstacle_vertex_count);
 
 
 	// The following block is modified copy from RVO2D::AddObstacle()
 	// The following block is modified copy from RVO2D::AddObstacle()
@@ -1128,6 +1134,11 @@ void NavMap::_update_rvo_obstacles_tree_2d() {
 		real_t _obstacle_height = obstacle->get_height();
 		real_t _obstacle_height = obstacle->get_height();
 
 
 		for (const Vector3 &_obstacle_vertex : _obstacle_vertices) {
 		for (const Vector3 &_obstacle_vertex : _obstacle_vertices) {
+#ifdef TOOLS_ENABLED
+			if (_obstacle_vertex.y != 0) {
+				WARN_PRINT_ONCE("Y coordinates of static obstacle vertices are ignored. Please use obstacle position Y to change elevation of obstacle.");
+			}
+#endif
 			rvo_2d_vertices.push_back(RVO2D::Vector2(_obstacle_vertex.x + _obstacle_position.x, _obstacle_vertex.z + _obstacle_position.z));
 			rvo_2d_vertices.push_back(RVO2D::Vector2(_obstacle_vertex.x + _obstacle_position.x, _obstacle_vertex.z + _obstacle_position.z));
 		}
 		}
 
 

+ 0 - 1
modules/openxr/action_map/openxr_action_map.cpp

@@ -177,7 +177,6 @@ void OpenXRActionMap::create_default_action_sets() {
 	Ref<OpenXRAction> trigger_touch = action_set->add_new_action("trigger_touch", "Trigger touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> trigger_touch = action_set->add_new_action("trigger_touch", "Trigger touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip = action_set->add_new_action("grip", "Grip", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip = action_set->add_new_action("grip", "Grip", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip_click = action_set->add_new_action("grip_click", "Grip click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip_click = action_set->add_new_action("grip_click", "Grip click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
-	Ref<OpenXRAction> grip_touch = action_set->add_new_action("grip_touch", "Grip touching", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip_force = action_set->add_new_action("grip_force", "Grip force", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> grip_force = action_set->add_new_action("grip_force", "Grip force", OpenXRAction::OPENXR_ACTION_FLOAT, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> primary = action_set->add_new_action("primary", "Primary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> primary = action_set->add_new_action("primary", "Primary joystick/thumbstick/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> primary_click = action_set->add_new_action("primary_click", "Primary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");
 	Ref<OpenXRAction> primary_click = action_set->add_new_action("primary_click", "Primary joystick/thumbstick/trackpad click", OpenXRAction::OPENXR_ACTION_BOOL, "/user/hand/left,/user/hand/right");

+ 2 - 0
modules/tinyexr/image_loader_tinyexr.cpp

@@ -68,6 +68,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitF
 	if (ret != TINYEXR_SUCCESS) {
 	if (ret != TINYEXR_SUCCESS) {
 		if (err) {
 		if (err) {
 			ERR_PRINT(String(err));
 			ERR_PRINT(String(err));
+			FreeEXRErrorMessage(err);
 		}
 		}
 		return ERR_FILE_CORRUPT;
 		return ERR_FILE_CORRUPT;
 	}
 	}
@@ -86,6 +87,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, BitF
 	if (ret != TINYEXR_SUCCESS) {
 	if (ret != TINYEXR_SUCCESS) {
 		if (err) {
 		if (err) {
 			ERR_PRINT(String(err));
 			ERR_PRINT(String(err));
+			FreeEXRErrorMessage(err);
 		}
 		}
 		return ERR_FILE_CORRUPT;
 		return ERR_FILE_CORRUPT;
 	}
 	}

+ 18 - 1
modules/zip/zip_packer.cpp

@@ -72,7 +72,24 @@ Error ZIPPacker::start_file(const String &p_path) {
 	zipfi.internal_fa = 0;
 	zipfi.internal_fa = 0;
 	zipfi.external_fa = 0;
 	zipfi.external_fa = 0;
 
 
-	int err = zipOpenNewFileInZip(zf, p_path.utf8().get_data(), &zipfi, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
+	int err = zipOpenNewFileInZip4(zf,
+			p_path.utf8().get_data(),
+			&zipfi,
+			nullptr,
+			0,
+			nullptr,
+			0,
+			nullptr,
+			Z_DEFLATED,
+			Z_DEFAULT_COMPRESSION,
+			0,
+			-MAX_WBITS,
+			DEF_MEM_LEVEL,
+			Z_DEFAULT_STRATEGY,
+			nullptr,
+			0,
+			0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions.
+			1 << 11); // Bit 11 is the language encoding flag. When set, filename and comment fields must be encoded using UTF-8.
 	return err == ZIP_OK ? OK : FAILED;
 	return err == ZIP_OK ? OK : FAILED;
 }
 }
 
 

+ 14 - 8
platform/ios/export/export_plugin.cpp

@@ -2074,15 +2074,21 @@ bool EditorExportPlatformIOS::is_package_name_valid(const String &p_package, Str
 bool EditorExportPlatformIOS::_check_xcode_install() {
 bool EditorExportPlatformIOS::_check_xcode_install() {
 	static bool xcode_found = false;
 	static bool xcode_found = false;
 	if (!xcode_found) {
 	if (!xcode_found) {
-		String xcode_path;
-		List<String> args;
-		args.push_back("-p");
-		int ec = 0;
-		Error err = OS::get_singleton()->execute("xcode-select", args, &xcode_path, &ec, true);
-		if (err != OK || ec != 0) {
-			return false;
+		Vector<String> mdfind_paths;
+		List<String> mdfind_args;
+		mdfind_args.push_back("kMDItemCFBundleIdentifier=com.apple.dt.Xcode");
+
+		String output;
+		Error err = OS::get_singleton()->execute("mdfind", mdfind_args, &output);
+		if (err == OK) {
+			mdfind_paths = output.split("\n");
+		}
+		for (const String &found_path : mdfind_paths) {
+			xcode_found = !found_path.is_empty() && DirAccess::dir_exists_absolute(found_path.strip_edges());
+			if (xcode_found) {
+				break;
+			}
 		}
 		}
-		xcode_found = DirAccess::dir_exists_absolute(xcode_path.strip_edges());
 	}
 	}
 	return xcode_found;
 	return xcode_found;
 }
 }

+ 1 - 1
platform/linuxbsd/x11/display_server_x11.cpp

@@ -3875,7 +3875,7 @@ void DisplayServerX11::_xim_preedit_draw_callback(::XIM xim, ::XPointer client_d
 			ds->im_selection = Point2i();
 			ds->im_selection = Point2i();
 		}
 		}
 
 
-		OS_Unix::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
+		OS_Unix::get_singleton()->get_main_loop()->call_deferred(SNAME("notification"), MainLoop::NOTIFICATION_OS_IME_UPDATE);
 	}
 	}
 }
 }
 
 

+ 2 - 1
platform/macos/display_server_macos.mm

@@ -725,7 +725,8 @@ void DisplayServerMacOS::update_mouse_pos(DisplayServerMacOS::WindowData &p_wd,
 }
 }
 
 
 void DisplayServerMacOS::pop_last_key_event() {
 void DisplayServerMacOS::pop_last_key_event() {
-	if (key_event_pos > 0) {
+	// Does not pop last key event when it is an IME key event.
+	if (key_event_pos > 0 && key_event_buffer[key_event_pos - 1].raw) {
 		key_event_pos--;
 		key_event_pos--;
 	}
 	}
 }
 }

+ 3 - 9
platform/macos/export/export_plugin.cpp

@@ -2026,9 +2026,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
 
 
 bool EditorExportPlatformMacOS::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
 bool EditorExportPlatformMacOS::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
 	String err;
 	String err;
-	// Look for export templates (custom templates).
-	bool dvalid = false;
-	bool rvalid = false;
+	// Look for export templates (official templates first, then custom).
+	bool dvalid = exists_export_template("macos.zip", &err);
+	bool rvalid = dvalid; // Both in the same ZIP.
 
 
 	if (p_preset->get("custom_template/debug") != "") {
 	if (p_preset->get("custom_template/debug") != "") {
 		dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
 		dvalid = FileAccess::exists(p_preset->get("custom_template/debug"));
@@ -2043,12 +2043,6 @@ bool EditorExportPlatformMacOS::has_valid_export_configuration(const Ref<EditorE
 		}
 		}
 	}
 	}
 
 
-	// Look for export templates (official templates, check only is custom templates are not set).
-	if (!dvalid || !rvalid) {
-		dvalid = exists_export_template("macos.zip", &err);
-		rvalid = dvalid; // Both in the same ZIP.
-	}
-
 	bool valid = dvalid || rvalid;
 	bool valid = dvalid || rvalid;
 	r_missing_templates = !valid;
 	r_missing_templates = !valid;
 
 

+ 1 - 1
platform/macos/gl_manager_macos_angle.mm

@@ -48,7 +48,7 @@ EGLenum GLManagerANGLE_MacOS::_get_platform_extension_enum() const {
 Vector<EGLAttrib> GLManagerANGLE_MacOS::_get_platform_display_attributes() const {
 Vector<EGLAttrib> GLManagerANGLE_MacOS::_get_platform_display_attributes() const {
 	Vector<EGLAttrib> ret;
 	Vector<EGLAttrib> ret;
 	ret.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
 	ret.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
-	ret.push_back(EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
+	ret.push_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE);
 	ret.push_back(EGL_NONE);
 	ret.push_back(EGL_NONE);
 
 
 	return ret;
 	return ret;

+ 1 - 1
platform/windows/detect.py

@@ -481,7 +481,7 @@ def configure_msvc(env, vcvars_msvc_config):
     env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
     env["BUILDERS"]["ProgramOriginal"] = env["BUILDERS"]["Program"]
     env["BUILDERS"]["Program"] = methods.precious_program
     env["BUILDERS"]["Program"] = methods.precious_program
 
 
-    env.Append(LINKFLAGS=["/NATVIS:platform\windows\godot.natvis"])
+    env.Append(LINKFLAGS=["/NATVIS:platform\\windows\\godot.natvis"])
     env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
     env.AppendUnique(LINKFLAGS=["/STACK:" + str(STACK_SIZE)])
 
 
 
 

+ 1 - 3
platform/windows/display_server_windows.cpp

@@ -2958,9 +2958,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
 			}
 			}
 		} break;
 		} break;
 		case WM_MOUSEACTIVATE: {
 		case WM_MOUSEACTIVATE: {
-			if (windows[window_id].no_focus) {
-				return MA_NOACTIVATEANDEAT; // Do not activate, and discard mouse messages.
-			} else if (windows[window_id].is_popup) {
+			if (windows[window_id].no_focus || windows[window_id].is_popup) {
 				return MA_NOACTIVATE; // Do not activate, but process mouse messages.
 				return MA_NOACTIVATE; // Do not activate, but process mouse messages.
 			}
 			}
 		} break;
 		} break;

+ 7 - 5
scene/2d/navigation_agent_2d.cpp

@@ -294,6 +294,13 @@ NavigationAgent2D::NavigationAgent2D() {
 	NavigationServer2D::get_singleton()->agent_set_time_horizon_obstacles(agent, time_horizon_obstacles);
 	NavigationServer2D::get_singleton()->agent_set_time_horizon_obstacles(agent, time_horizon_obstacles);
 	NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
 	NavigationServer2D::get_singleton()->agent_set_radius(agent, radius);
 	NavigationServer2D::get_singleton()->agent_set_max_speed(agent, max_speed);
 	NavigationServer2D::get_singleton()->agent_set_max_speed(agent, max_speed);
+	NavigationServer2D::get_singleton()->agent_set_avoidance_layers(agent, avoidance_layers);
+	NavigationServer2D::get_singleton()->agent_set_avoidance_mask(agent, avoidance_mask);
+	NavigationServer2D::get_singleton()->agent_set_avoidance_priority(agent, avoidance_priority);
+	NavigationServer2D::get_singleton()->agent_set_avoidance_enabled(agent, avoidance_enabled);
+	if (avoidance_enabled) {
+		NavigationServer2D::get_singleton()->agent_set_avoidance_callback(agent, callable_mp(this, &NavigationAgent2D::_avoidance_done));
+	}
 
 
 	// Preallocate query and result objects to improve performance.
 	// Preallocate query and result objects to improve performance.
 	navigation_query = Ref<NavigationPathQueryParameters2D>();
 	navigation_query = Ref<NavigationPathQueryParameters2D>();
@@ -302,11 +309,6 @@ NavigationAgent2D::NavigationAgent2D() {
 	navigation_result = Ref<NavigationPathQueryResult2D>();
 	navigation_result = Ref<NavigationPathQueryResult2D>();
 	navigation_result.instantiate();
 	navigation_result.instantiate();
 
 
-	set_avoidance_layers(avoidance_layers);
-	set_avoidance_mask(avoidance_mask);
-	set_avoidance_priority(avoidance_priority);
-	set_avoidance_enabled(avoidance_enabled);
-
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	NavigationServer2D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent2D::_navigation_debug_changed));
 	NavigationServer2D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent2D::_navigation_debug_changed));
 #endif // DEBUG_ENABLED
 #endif // DEBUG_ENABLED

+ 12 - 0
scene/2d/navigation_link_2d.cpp

@@ -36,6 +36,8 @@
 #include "servers/navigation_server_3d.h"
 #include "servers/navigation_server_3d.h"
 
 
 void NavigationLink2D::_bind_methods() {
 void NavigationLink2D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationLink2D::get_rid);
+
 	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
 	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
 	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);
 	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);
 
 
@@ -175,6 +177,10 @@ bool NavigationLink2D::_edit_is_selected_on_click(const Point2 &p_point, double
 }
 }
 #endif // TOOLS_ENABLED
 #endif // TOOLS_ENABLED
 
 
+RID NavigationLink2D::get_rid() const {
+	return link;
+}
+
 void NavigationLink2D::set_enabled(bool p_enabled) {
 void NavigationLink2D::set_enabled(bool p_enabled) {
 	if (enabled == p_enabled) {
 	if (enabled == p_enabled) {
 		return;
 		return;
@@ -343,7 +349,13 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const {
 
 
 NavigationLink2D::NavigationLink2D() {
 NavigationLink2D::NavigationLink2D() {
 	link = NavigationServer2D::get_singleton()->link_create();
 	link = NavigationServer2D::get_singleton()->link_create();
+
 	NavigationServer2D::get_singleton()->link_set_owner_id(link, get_instance_id());
 	NavigationServer2D::get_singleton()->link_set_owner_id(link, get_instance_id());
+	NavigationServer2D::get_singleton()->link_set_enter_cost(link, enter_cost);
+	NavigationServer2D::get_singleton()->link_set_travel_cost(link, travel_cost);
+	NavigationServer2D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
+	NavigationServer2D::get_singleton()->link_set_bidirectional(link, bidirectional);
+	NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);
 
 
 	set_notify_transform(true);
 	set_notify_transform(true);
 	set_hide_clip_children(true);
 	set_hide_clip_children(true);

+ 1 - 0
scene/2d/navigation_link_2d.h

@@ -61,6 +61,7 @@ public:
 	virtual Rect2 _edit_get_rect() const override;
 	virtual Rect2 _edit_get_rect() const override;
 	virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
 	virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
 #endif
 #endif
+	RID get_rid() const;
 
 
 	void set_enabled(bool p_enabled);
 	void set_enabled(bool p_enabled);
 	bool is_enabled() const { return enabled; }
 	bool is_enabled() const { return enabled; }

+ 4 - 4
scene/2d/navigation_obstacle_2d.cpp

@@ -148,10 +148,10 @@ void NavigationObstacle2D::_notification(int p_what) {
 NavigationObstacle2D::NavigationObstacle2D() {
 NavigationObstacle2D::NavigationObstacle2D() {
 	obstacle = NavigationServer2D::get_singleton()->obstacle_create();
 	obstacle = NavigationServer2D::get_singleton()->obstacle_create();
 
 
-	set_radius(radius);
-	set_vertices(vertices);
-	set_avoidance_layers(avoidance_layers);
-	set_avoidance_enabled(avoidance_enabled);
+	NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, radius);
+	NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, vertices);
+	NavigationServer2D::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers);
+	NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
 }
 }
 
 
 NavigationObstacle2D::~NavigationObstacle2D() {
 NavigationObstacle2D::~NavigationObstacle2D() {

+ 11 - 1
scene/2d/navigation_region_2d.cpp

@@ -35,6 +35,10 @@
 #include "scene/resources/world_2d.h"
 #include "scene/resources/world_2d.h"
 #include "servers/navigation_server_2d.h"
 #include "servers/navigation_server_2d.h"
 
 
+RID NavigationRegion2D::get_rid() const {
+	return region;
+}
+
 void NavigationRegion2D::set_enabled(bool p_enabled) {
 void NavigationRegion2D::set_enabled(bool p_enabled) {
 	if (enabled == p_enabled) {
 	if (enabled == p_enabled) {
 		return;
 		return;
@@ -136,7 +140,7 @@ real_t NavigationRegion2D::get_travel_cost() const {
 }
 }
 
 
 RID NavigationRegion2D::get_region_rid() const {
 RID NavigationRegion2D::get_region_rid() const {
-	return region;
+	return get_rid();
 }
 }
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
@@ -165,6 +169,7 @@ void NavigationRegion2D::_notification(int p_what) {
 
 
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
 			set_physics_process_internal(false);
 			set_physics_process_internal(false);
+			_region_update_transform();
 		} break;
 		} break;
 
 
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
@@ -279,6 +284,8 @@ PackedStringArray NavigationRegion2D::get_configuration_warnings() const {
 }
 }
 
 
 void NavigationRegion2D::_bind_methods() {
 void NavigationRegion2D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationRegion2D::get_rid);
+
 	ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navigation_polygon"), &NavigationRegion2D::set_navigation_polygon);
 	ClassDB::bind_method(D_METHOD("set_navigation_polygon", "navigation_polygon"), &NavigationRegion2D::set_navigation_polygon);
 	ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationRegion2D::get_navigation_polygon);
 	ClassDB::bind_method(D_METHOD("get_navigation_polygon"), &NavigationRegion2D::get_navigation_polygon);
 
 
@@ -356,6 +363,9 @@ NavigationRegion2D::NavigationRegion2D() {
 	NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
 	NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
 	NavigationServer2D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
 	NavigationServer2D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
 	NavigationServer2D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
 	NavigationServer2D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
+	NavigationServer2D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
+	NavigationServer2D::get_singleton()->region_set_use_edge_connections(region, use_edge_connections);
+	NavigationServer2D::get_singleton()->region_set_enabled(region, enabled);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	NavigationServer2D::get_singleton()->connect(SNAME("map_changed"), callable_mp(this, &NavigationRegion2D::_navigation_map_changed));
 	NavigationServer2D::get_singleton()->connect(SNAME("map_changed"), callable_mp(this, &NavigationRegion2D::_navigation_map_changed));

+ 1 - 0
scene/2d/navigation_region_2d.h

@@ -76,6 +76,7 @@ public:
 	virtual Rect2 _edit_get_rect() const override;
 	virtual Rect2 _edit_get_rect() const override;
 	virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
 	virtual bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const override;
 #endif
 #endif
+	RID get_rid() const;
 
 
 	void set_enabled(bool p_enabled);
 	void set_enabled(bool p_enabled);
 	bool is_enabled() const;
 	bool is_enabled() const;

+ 1 - 1
scene/2d/tile_map.cpp

@@ -1191,7 +1191,7 @@ void TileMapLayer::_scenes_update() {
 	const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
 	const Ref<TileSet> &tile_set = tile_map_node->get_tileset();
 
 
 	// Check if we should cleanup everything.
 	// Check if we should cleanup everything.
-	bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid() || !tile_map_node->is_visible_in_tree();
+	bool forced_cleanup = in_destructor || !enabled || !tile_map_node->is_inside_tree() || !tile_set.is_valid();
 
 
 	if (forced_cleanup) {
 	if (forced_cleanup) {
 		// Clean everything.
 		// Clean everything.

+ 8 - 6
scene/3d/navigation_agent_3d.cpp

@@ -327,6 +327,14 @@ NavigationAgent3D::NavigationAgent3D() {
 	NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
 	NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
 	NavigationServer3D::get_singleton()->agent_set_height(agent, height);
 	NavigationServer3D::get_singleton()->agent_set_height(agent, height);
 	NavigationServer3D::get_singleton()->agent_set_max_speed(agent, max_speed);
 	NavigationServer3D::get_singleton()->agent_set_max_speed(agent, max_speed);
+	NavigationServer3D::get_singleton()->agent_set_avoidance_layers(agent, avoidance_layers);
+	NavigationServer3D::get_singleton()->agent_set_avoidance_mask(agent, avoidance_mask);
+	NavigationServer3D::get_singleton()->agent_set_avoidance_priority(agent, avoidance_priority);
+	NavigationServer3D::get_singleton()->agent_set_use_3d_avoidance(agent, use_3d_avoidance);
+	NavigationServer3D::get_singleton()->agent_set_avoidance_enabled(agent, avoidance_enabled);
+	if (avoidance_enabled) {
+		NavigationServer3D::get_singleton()->agent_set_avoidance_callback(agent, callable_mp(this, &NavigationAgent3D::_avoidance_done));
+	}
 
 
 	// Preallocate query and result objects to improve performance.
 	// Preallocate query and result objects to improve performance.
 	navigation_query = Ref<NavigationPathQueryParameters3D>();
 	navigation_query = Ref<NavigationPathQueryParameters3D>();
@@ -335,12 +343,6 @@ NavigationAgent3D::NavigationAgent3D() {
 	navigation_result = Ref<NavigationPathQueryResult3D>();
 	navigation_result = Ref<NavigationPathQueryResult3D>();
 	navigation_result.instantiate();
 	navigation_result.instantiate();
 
 
-	set_avoidance_layers(avoidance_layers);
-	set_avoidance_mask(avoidance_mask);
-	set_avoidance_priority(avoidance_priority);
-	set_use_3d_avoidance(use_3d_avoidance);
-	set_avoidance_enabled(avoidance_enabled);
-
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent3D::_navigation_debug_changed));
 	NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationAgent3D::_navigation_debug_changed));
 #endif // DEBUG_ENABLED
 #endif // DEBUG_ENABLED

+ 12 - 0
scene/3d/navigation_link_3d.cpp

@@ -147,6 +147,8 @@ void NavigationLink3D::_update_debug_mesh() {
 #endif // DEBUG_ENABLED
 #endif // DEBUG_ENABLED
 
 
 void NavigationLink3D::_bind_methods() {
 void NavigationLink3D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationLink3D::get_rid);
+
 	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
 	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
 	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);
 	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);
 
 
@@ -263,7 +265,13 @@ void NavigationLink3D::_notification(int p_what) {
 
 
 NavigationLink3D::NavigationLink3D() {
 NavigationLink3D::NavigationLink3D() {
 	link = NavigationServer3D::get_singleton()->link_create();
 	link = NavigationServer3D::get_singleton()->link_create();
+
 	NavigationServer3D::get_singleton()->link_set_owner_id(link, get_instance_id());
 	NavigationServer3D::get_singleton()->link_set_owner_id(link, get_instance_id());
+	NavigationServer3D::get_singleton()->link_set_enter_cost(link, enter_cost);
+	NavigationServer3D::get_singleton()->link_set_travel_cost(link, travel_cost);
+	NavigationServer3D::get_singleton()->link_set_navigation_layers(link, navigation_layers);
+	NavigationServer3D::get_singleton()->link_set_bidirectional(link, bidirectional);
+	NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);
 
 
 	set_notify_transform(true);
 	set_notify_transform(true);
 }
 }
@@ -284,6 +292,10 @@ NavigationLink3D::~NavigationLink3D() {
 #endif // DEBUG_ENABLED
 #endif // DEBUG_ENABLED
 }
 }
 
 
+RID NavigationLink3D::get_rid() const {
+	return link;
+}
+
 void NavigationLink3D::set_enabled(bool p_enabled) {
 void NavigationLink3D::set_enabled(bool p_enabled) {
 	if (enabled == p_enabled) {
 	if (enabled == p_enabled) {
 		return;
 		return;

+ 2 - 0
scene/3d/navigation_link_3d.h

@@ -67,6 +67,8 @@ public:
 	NavigationLink3D();
 	NavigationLink3D();
 	~NavigationLink3D();
 	~NavigationLink3D();
 
 
+	RID get_rid() const;
+
 	void set_enabled(bool p_enabled);
 	void set_enabled(bool p_enabled);
 	bool is_enabled() const { return enabled; }
 	bool is_enabled() const { return enabled; }
 
 

+ 5 - 7
scene/3d/navigation_obstacle_3d.cpp

@@ -167,13 +167,11 @@ NavigationObstacle3D::NavigationObstacle3D() {
 	obstacle = NavigationServer3D::get_singleton()->obstacle_create();
 	obstacle = NavigationServer3D::get_singleton()->obstacle_create();
 
 
 	NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, height);
 	NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, height);
-
-	set_radius(radius);
-	set_height(height);
-	set_vertices(vertices);
-	set_avoidance_layers(avoidance_layers);
-	set_avoidance_enabled(avoidance_enabled);
-	set_use_3d_avoidance(use_3d_avoidance);
+	NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, radius);
+	NavigationServer3D::get_singleton()->obstacle_set_vertices(obstacle, vertices);
+	NavigationServer3D::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers);
+	NavigationServer3D::get_singleton()->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance);
+	NavigationServer3D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	NavigationServer3D::get_singleton()->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug));
 	NavigationServer3D::get_singleton()->connect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug));

+ 10 - 1
scene/3d/navigation_region_3d.cpp

@@ -33,6 +33,10 @@
 #include "scene/resources/navigation_mesh_source_geometry_data_3d.h"
 #include "scene/resources/navigation_mesh_source_geometry_data_3d.h"
 #include "servers/navigation_server_3d.h"
 #include "servers/navigation_server_3d.h"
 
 
+RID NavigationRegion3D::get_rid() const {
+	return region;
+}
+
 void NavigationRegion3D::set_enabled(bool p_enabled) {
 void NavigationRegion3D::set_enabled(bool p_enabled) {
 	if (enabled == p_enabled) {
 	if (enabled == p_enabled) {
 		return;
 		return;
@@ -154,7 +158,7 @@ real_t NavigationRegion3D::get_travel_cost() const {
 }
 }
 
 
 RID NavigationRegion3D::get_region_rid() const {
 RID NavigationRegion3D::get_region_rid() const {
-	return region;
+	return get_rid();
 }
 }
 
 
 void NavigationRegion3D::_notification(int p_what) {
 void NavigationRegion3D::_notification(int p_what) {
@@ -275,6 +279,8 @@ PackedStringArray NavigationRegion3D::get_configuration_warnings() const {
 }
 }
 
 
 void NavigationRegion3D::_bind_methods() {
 void NavigationRegion3D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationRegion3D::get_rid);
+
 	ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navigation_mesh"), &NavigationRegion3D::set_navigation_mesh);
 	ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navigation_mesh"), &NavigationRegion3D::set_navigation_mesh);
 	ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh);
 	ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationRegion3D::get_navigation_mesh);
 
 
@@ -410,6 +416,9 @@ NavigationRegion3D::NavigationRegion3D() {
 	NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
 	NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
 	NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
 	NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
 	NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
 	NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
+	NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
+	NavigationServer3D::get_singleton()->region_set_use_edge_connections(region, use_edge_connections);
+	NavigationServer3D::get_singleton()->region_set_enabled(region, enabled);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	NavigationServer3D::get_singleton()->connect(SNAME("map_changed"), callable_mp(this, &NavigationRegion3D::_navigation_map_changed));
 	NavigationServer3D::get_singleton()->connect(SNAME("map_changed"), callable_mp(this, &NavigationRegion3D::_navigation_map_changed));

+ 2 - 0
scene/3d/navigation_region_3d.h

@@ -73,6 +73,8 @@ protected:
 #endif // DISABLE_DEPRECATED
 #endif // DISABLE_DEPRECATED
 
 
 public:
 public:
+	RID get_rid() const;
+
 	void set_enabled(bool p_enabled);
 	void set_enabled(bool p_enabled);
 	bool is_enabled() const;
 	bool is_enabled() const;
 
 

+ 1 - 0
scene/animation/animation_mixer.cpp

@@ -1985,6 +1985,7 @@ void AnimationMixer::reset() {
 }
 }
 
 
 void AnimationMixer::restore(const Ref<AnimatedValuesBackup> &p_backup) {
 void AnimationMixer::restore(const Ref<AnimatedValuesBackup> &p_backup) {
+	ERR_FAIL_COND(p_backup.is_null());
 	track_cache = p_backup->get_data();
 	track_cache = p_backup->get_data();
 	_blend_apply();
 	_blend_apply();
 	track_cache = HashMap<NodePath, AnimationMixer::TrackCache *>();
 	track_cache = HashMap<NodePath, AnimationMixer::TrackCache *>();

+ 1 - 1
scene/animation/animation_player.cpp

@@ -233,7 +233,7 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
 		pi.delta = delta;
 		pi.delta = delta;
 		pi.seeked = p_seeked;
 		pi.seeked = p_seeked;
 	}
 	}
-	pi.is_external_seeking = false;
+	pi.is_external_seeking = true; // AnimationPlayer doesn't have internal seeking.
 	pi.looped_flag = looped_flag;
 	pi.looped_flag = looped_flag;
 	pi.weight = p_blend;
 	pi.weight = p_blend;
 	make_animation_instance(cd.from->name, pi);
 	make_animation_instance(cd.from->name, pi);

+ 8 - 5
scene/animation/tween.cpp

@@ -549,9 +549,12 @@ void PropertyTweener::start() {
 		return;
 		return;
 	}
 	}
 
 
-	if (do_continue && Math::is_zero_approx(delay)) {
-		initial_val = target_instance->get_indexed(property);
-		do_continue = false;
+	if (do_continue) {
+		if (Math::is_zero_approx(delay)) {
+			initial_val = target_instance->get_indexed(property);
+		} else {
+			do_continue_delayed = true;
+		}
 	}
 	}
 
 
 	if (relative) {
 	if (relative) {
@@ -576,10 +579,10 @@ bool PropertyTweener::step(double &r_delta) {
 	if (elapsed_time < delay) {
 	if (elapsed_time < delay) {
 		r_delta = 0;
 		r_delta = 0;
 		return true;
 		return true;
-	} else if (do_continue && !Math::is_zero_approx(delay)) {
+	} else if (do_continue_delayed && !Math::is_zero_approx(delay)) {
 		initial_val = target_instance->get_indexed(property);
 		initial_val = target_instance->get_indexed(property);
 		delta_val = Animation::subtract_variant(final_val, initial_val);
 		delta_val = Animation::subtract_variant(final_val, initial_val);
-		do_continue = false;
+		do_continue_delayed = false;
 	}
 	}
 
 
 	double time = MIN(elapsed_time - delay, duration);
 	double time = MIN(elapsed_time - delay, duration);

+ 1 - 0
scene/animation/tween.h

@@ -225,6 +225,7 @@ private:
 
 
 	double delay = 0;
 	double delay = 0;
 	bool do_continue = true;
 	bool do_continue = true;
+	bool do_continue_delayed = false;
 	bool relative = false;
 	bool relative = false;
 };
 };
 
 

+ 3 - 1
scene/gui/rich_text_label.cpp

@@ -1771,7 +1771,7 @@ void RichTextLabel::_scroll_changed(double) {
 		return;
 		return;
 	}
 	}
 
 
-	if (scroll_follow && vscroll->get_value() >= (vscroll->get_max() - vscroll->get_page())) {
+	if (scroll_follow && vscroll->get_value() >= (vscroll->get_max() - Math::round(vscroll->get_page()))) {
 		scroll_following = true;
 		scroll_following = true;
 	} else {
 	} else {
 		scroll_following = false;
 		scroll_following = false;
@@ -3121,6 +3121,8 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline)
 		current_char_ofs += t->text.length();
 		current_char_ofs += t->text.length();
 	} else if (p_item->type == ITEM_IMAGE) {
 	} else if (p_item->type == ITEM_IMAGE) {
 		current_char_ofs++;
 		current_char_ofs++;
+	} else if (p_item->type == ITEM_NEWLINE) {
+		current_char_ofs++;
 	}
 	}
 
 
 	if (p_enter) {
 	if (p_enter) {

+ 10 - 0
scene/gui/video_stream_player.cpp

@@ -237,6 +237,12 @@ bool VideoStreamPlayer::has_loop() const {
 void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
 void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
 	stop();
 	stop();
 
 
+	// Make sure to handle stream changes seamlessly, e.g. when done via
+	// translation remapping.
+	if (stream.is_valid()) {
+		stream->disconnect_changed(callable_mp(this, &VideoStreamPlayer::set_stream));
+	}
+
 	AudioServer::get_singleton()->lock();
 	AudioServer::get_singleton()->lock();
 	mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
 	mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
 	stream = p_stream;
 	stream = p_stream;
@@ -248,6 +254,10 @@ void VideoStreamPlayer::set_stream(const Ref<VideoStream> &p_stream) {
 	}
 	}
 	AudioServer::get_singleton()->unlock();
 	AudioServer::get_singleton()->unlock();
 
 
+	if (stream.is_valid()) {
+		stream->connect_changed(callable_mp(this, &VideoStreamPlayer::set_stream).bind(stream));
+	}
+
 	if (!playback.is_null()) {
 	if (!playback.is_null()) {
 		playback->set_paused(paused);
 		playback->set_paused(paused);
 		texture = playback->get_texture();
 		texture = playback->get_texture();

+ 18 - 8
scene/main/window.cpp

@@ -284,7 +284,13 @@ void Window::set_title(const String &p_title) {
 		embedder->_sub_window_update(this);
 		embedder->_sub_window_update(this);
 	} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
 	} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
 		DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
 		DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
-		_update_window_size();
+		if (keep_title_visible) {
+			Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+			Size2i size_limit = get_clamped_minimum_size();
+			if (title_size.x > size_limit.x || title_size.y > size_limit.y) {
+				_update_window_size();
+			}
+		}
 	}
 	}
 }
 }
 
 
@@ -961,6 +967,10 @@ Size2i Window::_clamp_window_size(const Size2i &p_size) {
 
 
 void Window::_update_window_size() {
 void Window::_update_window_size() {
 	Size2i size_limit = get_clamped_minimum_size();
 	Size2i size_limit = get_clamped_minimum_size();
+	if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID && keep_title_visible) {
+		Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+		size_limit = size_limit.max(title_size);
+	}
 
 
 	size = size.max(size_limit);
 	size = size.max(size_limit);
 
 
@@ -992,12 +1002,6 @@ void Window::_update_window_size() {
 		}
 		}
 
 
 		DisplayServer::get_singleton()->window_set_max_size(max_size_used, window_id);
 		DisplayServer::get_singleton()->window_set_max_size(max_size_used, window_id);
-
-		if (keep_title_visible) {
-			Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
-			size_limit = size_limit.max(title_size);
-		}
-
 		DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id);
 		DisplayServer::get_singleton()->window_set_min_size(size_limit, window_id);
 		DisplayServer::get_singleton()->window_set_size(size, window_id);
 		DisplayServer::get_singleton()->window_set_size(size, window_id);
 	}
 	}
@@ -1297,7 +1301,13 @@ void Window::_notification(int p_what) {
 
 
 			if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
 			if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
 				DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
 				DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
-				_update_window_size();
+				if (keep_title_visible) {
+					Size2i title_size = DisplayServer::get_singleton()->window_get_title_size(tr_title, window_id);
+					Size2i size_limit = get_clamped_minimum_size();
+					if (title_size.x > size_limit.x || title_size.y > size_limit.y) {
+						_update_window_size();
+					}
+				}
 			}
 			}
 		} break;
 		} break;
 
 

+ 2 - 2
scene/resources/camera_attributes.cpp

@@ -286,10 +286,10 @@ void CameraAttributesPractical::_bind_methods() {
 	ADD_GROUP("DOF Blur", "dof_blur_");
 	ADD_GROUP("DOF Blur", "dof_blur_");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_far_distance", "get_dof_blur_far_distance");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01,exp"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_RANGE, "0.01,8192,0.01,exp,suffix:m"), "set_dof_blur_near_distance", "get_dof_blur_near_distance");
-	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01,exp"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
+	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_RANGE, "-1,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount");
 
 
 	ADD_GROUP("Auto Exposure", "auto_exposure_");
 	ADD_GROUP("Auto Exposure", "auto_exposure_");

+ 1 - 1
scene/resources/importer_mesh.cpp

@@ -969,7 +969,7 @@ Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Ref<MeshConvexDecompos
 				if (found_vertex) {
 				if (found_vertex) {
 					index = found_vertex->value;
 					index = found_vertex->value;
 				} else {
 				} else {
-					index = ++vertex_count;
+					index = vertex_count++;
 					vertex_map[vertex] = index;
 					vertex_map[vertex] = index;
 					vertex_w[index] = vertex;
 					vertex_w[index] = vertex;
 				}
 				}

+ 1 - 1
scene/resources/material.cpp

@@ -3167,7 +3167,7 @@ bool StandardMaterial3D::_set(const StringName &p_name, const Variant &p_value)
 			{ "flags_use_shadow_to_opacity", "shadow_to_opacity" },
 			{ "flags_use_shadow_to_opacity", "shadow_to_opacity" },
 			{ "flags_no_depth_test", "no_depth_test" },
 			{ "flags_no_depth_test", "no_depth_test" },
 			{ "flags_use_point_size", "use_point_size" },
 			{ "flags_use_point_size", "use_point_size" },
-			{ "flags_fixed_size", "fixed_Size" },
+			{ "flags_fixed_size", "fixed_size" },
 			{ "flags_albedo_tex_force_srgb", "albedo_texture_force_srgb" },
 			{ "flags_albedo_tex_force_srgb", "albedo_texture_force_srgb" },
 			{ "flags_do_not_receive_shadows", "disable_receive_shadows" },
 			{ "flags_do_not_receive_shadows", "disable_receive_shadows" },
 			{ "flags_disable_ambient_light", "disable_ambient_light" },
 			{ "flags_disable_ambient_light", "disable_ambient_light" },

+ 14 - 9
scene/resources/tile_set.cpp

@@ -1839,20 +1839,25 @@ Vector<Vector<Ref<Texture2D>>> TileSet::generate_terrains_icons(Size2i p_size) {
 	// Generate the icons.
 	// Generate the icons.
 	for (int terrain_set = 0; terrain_set < get_terrain_sets_count(); terrain_set++) {
 	for (int terrain_set = 0; terrain_set < get_terrain_sets_count(); terrain_set++) {
 		for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
 		for (int terrain = 0; terrain < get_terrains_count(terrain_set); terrain++) {
-			Ref<Image> image;
-			image.instantiate();
+			Ref<Image> dst_image;
+			dst_image.instantiate();
 			if (counts[terrain_set][terrain].count > 0) {
 			if (counts[terrain_set][terrain].count > 0) {
 				// Get the best tile.
 				// Get the best tile.
-				Ref<Texture2D> texture = counts[terrain_set][terrain].texture;
+				Ref<Texture2D> src_texture = counts[terrain_set][terrain].texture;
+				ERR_FAIL_COND_V(src_texture.is_null(), output);
+				Ref<Image> src_image = src_texture->get_image();
+				ERR_FAIL_COND_V(src_image.is_null(), output);
 				Rect2i region = counts[terrain_set][terrain].region;
 				Rect2i region = counts[terrain_set][terrain].region;
-				image->initialize_data(region.size.x, region.size.y, false, Image::FORMAT_RGBA8);
-				image->blit_rect(texture->get_image(), region, Point2i());
-				image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST);
+
+				dst_image->initialize_data(region.size.x, region.size.y, false, src_image->get_format());
+				dst_image->blit_rect(src_image, region, Point2i());
+				dst_image->convert(Image::FORMAT_RGBA8);
+				dst_image->resize(p_size.x, p_size.y, Image::INTERPOLATE_NEAREST);
 			} else {
 			} else {
-				image->initialize_data(1, 1, false, Image::FORMAT_RGBA8);
-				image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain));
+				dst_image->initialize_data(1, 1, false, Image::FORMAT_RGBA8);
+				dst_image->set_pixel(0, 0, get_terrain_color(terrain_set, terrain));
 			}
 			}
-			Ref<ImageTexture> icon = ImageTexture::create_from_image(image);
+			Ref<ImageTexture> icon = ImageTexture::create_from_image(dst_image);
 			icon->set_size_override(p_size);
 			icon->set_size_override(p_size);
 			output.write[terrain_set].write[terrain] = icon;
 			output.write[terrain_set].write[terrain] = icon;
 		}
 		}

+ 1 - 0
scene/resources/video_stream.cpp

@@ -172,6 +172,7 @@ Ref<VideoStreamPlayback> VideoStream::instantiate_playback() {
 
 
 void VideoStream::set_file(const String &p_file) {
 void VideoStream::set_file(const String &p_file) {
 	file = p_file;
 	file = p_file;
+	emit_changed();
 }
 }
 
 
 String VideoStream::get_file() {
 String VideoStream::get_file() {

+ 2 - 2
servers/rendering/renderer_rd/effects/ss_effects.cpp

@@ -950,7 +950,7 @@ void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_rende
 
 
 	RD::get_singleton()->draw_command_end_label(); // SSIL
 	RD::get_singleton()->draw_command_end_label(); // SSIL
 
 
-	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); // Zeroing importance_map_load_counter depends on us.
 
 
 	int zero[1] = { 0 };
 	int zero[1] = { 0 };
 	RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
 	RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
@@ -1332,7 +1332,7 @@ void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORe
 		RD::get_singleton()->draw_command_end_label(); // Interleave
 		RD::get_singleton()->draw_command_end_label(); // Interleave
 	}
 	}
 	RD::get_singleton()->draw_command_end_label(); //SSAO
 	RD::get_singleton()->draw_command_end_label(); //SSAO
-	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
+	RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_TRANSFER); // Zeroing importance_map_load_counter depends on us.
 
 
 	int zero[1] = { 0 };
 	int zero[1] = { 0 };
 	RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
 	RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier

Some files were not shown because too many files changed in this diff