summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--COPYRIGHT.txt66
-rw-r--r--core/config/engine.cpp8
-rw-r--r--core/config/engine.h3
-rw-r--r--core/core_bind.cpp17
-rw-r--r--core/core_bind.h5
-rw-r--r--core/io/pck_packer.cpp12
-rw-r--r--core/io/pck_packer.h4
-rw-r--r--core/io/resource.cpp19
-rw-r--r--core/io/resource.h5
-rw-r--r--core/variant/variant_op.h30
-rw-r--r--doc/classes/@GlobalScope.xml2
-rw-r--r--doc/classes/BaseButton.xml2
-rw-r--r--doc/classes/CanvasItem.xml9
-rw-r--r--doc/classes/EditorSettings.xml3
-rw-r--r--doc/classes/Engine.xml4
-rw-r--r--doc/classes/PCKPacker.xml4
-rw-r--r--doc/classes/ProjectSettings.xml5
-rw-r--r--doc/classes/Resource.xml49
-rw-r--r--doc/classes/ResourceSaver.xml8
-rw-r--r--doc/classes/TextEdit.xml3
-rwxr-xr-xdoc/tools/make_rst.py8
-rw-r--r--editor/code_editor.cpp3
-rw-r--r--editor/editor_sectioned_inspector.cpp33
-rw-r--r--editor/editor_sectioned_inspector.h12
-rw-r--r--editor/editor_settings.cpp3
-rw-r--r--editor/editor_settings_dialog.cpp4
-rw-r--r--editor/groups_editor.cpp2
-rw-r--r--editor/import_defaults_editor.cpp5
-rw-r--r--editor/project_settings_editor.cpp7
-rw-r--r--editor/shader_globals_editor.cpp1
-rw-r--r--main/main.cpp11
-rw-r--r--modules/godot_physics_3d/SCsub7
-rw-r--r--modules/godot_physics_3d/config.py6
-rw-r--r--modules/godot_physics_3d/gjk_epa.cpp (renamed from servers/physics_3d/gjk_epa.cpp)0
-rw-r--r--modules/godot_physics_3d/gjk_epa.h (renamed from servers/physics_3d/gjk_epa.h)0
-rw-r--r--modules/godot_physics_3d/godot_area_3d.cpp (renamed from servers/physics_3d/godot_area_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_area_3d.h (renamed from servers/physics_3d/godot_area_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_area_pair_3d.cpp (renamed from servers/physics_3d/godot_area_pair_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_area_pair_3d.h (renamed from servers/physics_3d/godot_area_pair_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_body_3d.cpp (renamed from servers/physics_3d/godot_body_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_body_3d.h (renamed from servers/physics_3d/godot_body_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_body_direct_state_3d.cpp (renamed from servers/physics_3d/godot_body_direct_state_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_body_direct_state_3d.h (renamed from servers/physics_3d/godot_body_direct_state_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_body_pair_3d.cpp (renamed from servers/physics_3d/godot_body_pair_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_body_pair_3d.h (renamed from servers/physics_3d/godot_body_pair_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_broad_phase_3d.cpp (renamed from servers/physics_3d/godot_broad_phase_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_broad_phase_3d.h (renamed from servers/physics_3d/godot_broad_phase_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_broad_phase_3d_bvh.cpp (renamed from servers/physics_3d/godot_broad_phase_3d_bvh.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_broad_phase_3d_bvh.h (renamed from servers/physics_3d/godot_broad_phase_3d_bvh.h)0
-rw-r--r--modules/godot_physics_3d/godot_collision_object_3d.cpp (renamed from servers/physics_3d/godot_collision_object_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_collision_object_3d.h (renamed from servers/physics_3d/godot_collision_object_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_collision_solver_3d.cpp (renamed from servers/physics_3d/godot_collision_solver_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_collision_solver_3d.h (renamed from servers/physics_3d/godot_collision_solver_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp (renamed from servers/physics_3d/godot_collision_solver_3d_sat.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_collision_solver_3d_sat.h (renamed from servers/physics_3d/godot_collision_solver_3d_sat.h)0
-rw-r--r--modules/godot_physics_3d/godot_constraint_3d.h (renamed from servers/physics_3d/godot_constraint_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_joint_3d.h (renamed from servers/physics_3d/godot_joint_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_physics_server_3d.cpp (renamed from servers/physics_3d/godot_physics_server_3d.cpp)6
-rw-r--r--modules/godot_physics_3d/godot_physics_server_3d.h (renamed from servers/physics_3d/godot_physics_server_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_shape_3d.cpp (renamed from servers/physics_3d/godot_shape_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_shape_3d.h (renamed from servers/physics_3d/godot_shape_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_soft_body_3d.cpp (renamed from servers/physics_3d/godot_soft_body_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_soft_body_3d.h (renamed from servers/physics_3d/godot_soft_body_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_space_3d.cpp (renamed from servers/physics_3d/godot_space_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_space_3d.h (renamed from servers/physics_3d/godot_space_3d.h)0
-rw-r--r--modules/godot_physics_3d/godot_step_3d.cpp (renamed from servers/physics_3d/godot_step_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/godot_step_3d.h (renamed from servers/physics_3d/godot_step_3d.h)0
-rw-r--r--modules/godot_physics_3d/joints/SCsub5
-rw-r--r--modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp (renamed from servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h (renamed from servers/physics_3d/joints/godot_cone_twist_joint_3d.h)4
-rw-r--r--modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp (renamed from servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h (renamed from servers/physics_3d/joints/godot_generic_6dof_joint_3d.h)4
-rw-r--r--modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp (renamed from servers/physics_3d/joints/godot_hinge_joint_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/joints/godot_hinge_joint_3d.h (renamed from servers/physics_3d/joints/godot_hinge_joint_3d.h)4
-rw-r--r--modules/godot_physics_3d/joints/godot_jacobian_entry_3d.h (renamed from servers/physics_3d/joints/godot_jacobian_entry_3d.h)0
-rw-r--r--modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp (renamed from servers/physics_3d/joints/godot_pin_joint_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/joints/godot_pin_joint_3d.h (renamed from servers/physics_3d/joints/godot_pin_joint_3d.h)4
-rw-r--r--modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp (renamed from servers/physics_3d/joints/godot_slider_joint_3d.cpp)0
-rw-r--r--modules/godot_physics_3d/joints/godot_slider_joint_3d.h (renamed from servers/physics_3d/joints/godot_slider_joint_3d.h)4
-rw-r--r--modules/godot_physics_3d/register_types.cpp61
-rw-r--r--modules/godot_physics_3d/register_types.h39
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs18
-rw-r--r--modules/mono/editor/bindings_generator.cpp153
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs76
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs11
-rw-r--r--modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml9
-rw-r--r--modules/openxr/extensions/openxr_composition_layer_extension.cpp11
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h3
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.cpp13
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper_extension.h4
-rw-r--r--modules/upnp/upnp.cpp4
-rw-r--r--platform/windows/detect.py16
-rw-r--r--scene/3d/physics/character_body_3d.cpp9
-rw-r--r--scene/gui/code_edit.cpp3
-rw-r--r--scene/gui/text_edit.cpp20
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/resources/external_texture.cpp3
-rw-r--r--scu_builders.py4
-rw-r--r--servers/SCsub1
-rw-r--r--servers/physics_3d/SCsub7
-rw-r--r--servers/physics_3d/joints/SCsub5
-rw-r--r--servers/physics_server_3d.cpp4
-rw-r--r--servers/physics_server_3d_dummy.h436
-rw-r--r--servers/register_server_types.cpp17
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h2
-rw-r--r--tests/scene/test_code_edit.h25
-rw-r--r--tests/scene/test_text_edit.h48
-rw-r--r--tests/test_main.cpp4
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/miniupnpc/include/miniupnpc.h19
-rw-r--r--thirdparty/miniupnpc/src/addr_is_reserved.c11
-rw-r--r--thirdparty/miniupnpc/src/minisoap.c7
-rw-r--r--thirdparty/miniupnpc/src/minissdpc.c9
-rw-r--r--thirdparty/miniupnpc/src/miniupnpc.c93
-rw-r--r--thirdparty/miniupnpc/src/miniupnpcstrings.h2
-rw-r--r--thirdparty/miniupnpc/src/miniwget.c44
-rw-r--r--thirdparty/miniupnpc/src/win32_snprintf.h4
117 files changed, 1237 insertions, 355 deletions
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 5b6dcbb567..c0bb756d2e 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -63,6 +63,39 @@ Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
+Files: ./modules/godot_physics_3d/gjk_epa.cpp
+ ./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp
+ ./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h
+ ./modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp
+ ./modules/godot_physics_3d/joints/godot_hinge_joint_3d_sw.h
+ ./modules/godot_physics_3d/joints/godot_jacobian_entry_3d_sw.h
+ ./modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp
+ ./modules/godot_physics_3d/joints/godot_pin_joint_3d.h
+ ./modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp
+ ./modules/godot_physics_3d/joints/godot_slider_joint_3d.h
+ ./modules/godot_physics_3d/godot_soft_body_3d.cpp
+ ./modules/godot_physics_3d/godot_soft_body_3d.h
+ ./modules/godot_physics_3d/godot_shape_3d.cpp
+ ./modules/godot_physics_3d/godot_shape_3d.h
+Comment: Bullet Continuous Collision Detection and Physics Library
+Copyright: 2003-2008, Erwin Coumans
+ 2014-present, Godot Engine contributors
+ 2007-2014, Juan Linietsky, Ariel Manzur
+License: Expat and Zlib
+
+Files: ./modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp
+Comment: Open Dynamics Engine
+Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
+License: BSD-3-clause
+
+Files: ./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
+ ./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h
+Comment: Bullet Continuous Collision Detection and Physics Library
+Copyright: 2007, Starbreeze Studios
+ 2014-present, Godot Engine contributors
+ 2007-2014, Juan Linietsky, Ariel Manzur
+License: Expat and Zlib
+
Files: ./modules/lightmapper_rd/lm_compute.glsl
Comment: Joint Non-Local Means (JNLM) denoiser
Copyright: 2020, Manuel Prandini
@@ -98,39 +131,6 @@ Comment: Chipmunk2D Joint Constraints
Copyright: 2007, Scott Lembcke
License: Expat
-Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
-Comment: Open Dynamics Engine
-Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
-License: BSD-3-clause
-
-Files: ./servers/physics_3d/gjk_epa.cpp
- ./servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
- ./servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
- ./servers/physics_3d/joints/hinge_joint_3d_sw.cpp
- ./servers/physics_3d/joints/hinge_joint_3d_sw.h
- ./servers/physics_3d/joints/jacobian_entry_3d_sw.h
- ./servers/physics_3d/joints/pin_joint_3d_sw.cpp
- ./servers/physics_3d/joints/pin_joint_3d_sw.h
- ./servers/physics_3d/joints/slider_joint_3d_sw.cpp
- ./servers/physics_3d/joints/slider_joint_3d_sw.h
- ./servers/physics_3d/soft_body_3d_sw.cpp
- ./servers/physics_3d/soft_body_3d_sw.h
- ./servers/physics_3d/shape_3d_sw.cpp
- ./servers/physics_3d/shape_3d_sw.h
-Comment: Bullet Continuous Collision Detection and Physics Library
-Copyright: 2003-2008, Erwin Coumans
- 2014-present, Godot Engine contributors
- 2007-2014, Juan Linietsky, Ariel Manzur
-License: Expat and Zlib
-
-Files: ./servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
- ./servers/physics_3d/joints/cone_twist_joint_3d_sw.h
-Comment: Bullet Continuous Collision Detection and Physics Library
-Copyright: 2007, Starbreeze Studios
- 2014-present, Godot Engine contributors
- 2007-2014, Juan Linietsky, Ariel Manzur
-License: Expat and Zlib
-
Files: ./servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
./servers/rendering/renderer_rd/shaders/ssao_blur.glsl
./servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 9cdc21fe8e..d77c913314 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -267,6 +267,14 @@ bool Engine::is_extra_gpu_memory_tracking_enabled() const {
return extra_gpu_memory_tracking;
}
+void Engine::set_print_to_stdout(bool p_enabled) {
+ CoreGlobals::print_line_enabled = p_enabled;
+}
+
+bool Engine::is_printing_to_stdout() const {
+ return CoreGlobals::print_line_enabled;
+}
+
void Engine::set_print_error_messages(bool p_enabled) {
CoreGlobals::print_error_enabled = p_enabled;
}
diff --git a/core/config/engine.h b/core/config/engine.h
index f858eba328..a0b1ffa981 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -128,6 +128,9 @@ public:
void set_time_scale(double p_scale);
double get_time_scale() const;
+ void set_print_to_stdout(bool p_enabled);
+ bool is_printing_to_stdout() const;
+
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
void print_header(const String &p_string) const;
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index bbfbb6e3cd..891e3a28c9 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -184,6 +184,10 @@ void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_form
::ResourceSaver::remove_resource_format_saver(p_format_saver);
}
+ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bool p_generate) {
+ return ::ResourceSaver::get_resource_id_for_path(p_path, p_generate);
+}
+
ResourceSaver *ResourceSaver::singleton = nullptr;
void ResourceSaver::_bind_methods() {
@@ -191,6 +195,7 @@ void ResourceSaver::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions);
ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver);
+ ClassDB::bind_method(D_METHOD("get_resource_id_for_path", "path", "generate"), &ResourceSaver::get_resource_id_for_path, DEFVAL(false));
BIND_BITFIELD_FLAG(FLAG_NONE);
BIND_BITFIELD_FLAG(FLAG_RELATIVE_PATHS);
@@ -1848,6 +1853,14 @@ String Engine::get_write_movie_path() const {
return ::Engine::get_singleton()->get_write_movie_path();
}
+void Engine::set_print_to_stdout(bool p_enabled) {
+ ::Engine::get_singleton()->set_print_to_stdout(p_enabled);
+}
+
+bool Engine::is_printing_to_stdout() const {
+ return ::Engine::get_singleton()->is_printing_to_stdout();
+}
+
void Engine::set_print_error_messages(bool p_enabled) {
::Engine::get_singleton()->set_print_error_messages(p_enabled);
}
@@ -1916,10 +1929,14 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_write_movie_path"), &Engine::get_write_movie_path);
+ ClassDB::bind_method(D_METHOD("set_print_to_stdout", "enabled"), &Engine::set_print_to_stdout);
+ ClassDB::bind_method(D_METHOD("is_printing_to_stdout"), &Engine::is_printing_to_stdout);
+
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_to_stdout"), "set_print_to_stdout", "is_printing_to_stdout");
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps");
diff --git a/core/core_bind.h b/core/core_bind.h
index 2a31e64425..ce0bde3c05 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -116,6 +116,8 @@ public:
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
+ ResourceUID::ID get_resource_id_for_path(const String &p_path, bool p_generate = false);
+
ResourceSaver() { singleton = this; }
};
@@ -567,6 +569,9 @@ public:
// `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect.
String get_write_movie_path() const;
+ void set_print_to_stdout(bool p_enabled);
+ bool is_printing_to_stdout() const;
+
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index a7c715c318..93179d9a11 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -47,12 +47,12 @@ static int _get_pad(int p_alignment, int p_n) {
}
void PCKPacker::_bind_methods() {
- ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
}
-Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) {
+Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const String &p_key, bool p_encrypt_directory) {
ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long).");
ERR_FAIL_COND_V_MSG(p_alignment <= 0, ERR_CANT_CREATE, "Invalid alignment, must be greater then 0.");
@@ -83,8 +83,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
}
enc_dir = p_encrypt_directory;
- file = FileAccess::open(p_file, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
+ file = FileAccess::open(p_pck_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_pck_path) + ".");
alignment = p_alignment;
@@ -106,7 +106,7 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
return OK;
}
-Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
+Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) {
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
@@ -117,7 +117,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
File pf;
// Simplify path here and on every 'files' access so that paths that have extra '/'
// symbols in them still match to the MD5 hash for the saved path.
- pf.path = p_file.simplify_path();
+ pf.path = p_pck_path.simplify_path();
pf.src_path = p_src;
pf.ofs = ofs;
pf.size = f->get_length();
diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h
index 8764fc90a0..5aac833532 100644
--- a/core/io/pck_packer.h
+++ b/core/io/pck_packer.h
@@ -58,8 +58,8 @@ class PCKPacker : public RefCounted {
Vector<File> files;
public:
- Error pck_start(const String &p_file, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
- Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false);
+ Error pck_start(const String &p_pck_path, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
+ Error add_file(const String &p_pck_path, const String &p_src, bool p_encrypt = false);
Error flush(bool p_verbose = false);
PCKPacker() {}
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 6177cba6a4..5f8a4b85a4 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -96,6 +96,7 @@ String Resource::get_path() const {
void Resource::set_path_cache(const String &p_path) {
path_cache = p_path;
+ GDVIRTUAL_CALL(_set_path_cache, p_path);
}
String Resource::generate_scene_unique_id() {
@@ -188,6 +189,7 @@ void Resource::disconnect_changed(const Callable &p_callable) {
}
void Resource::reset_state() {
+ GDVIRTUAL_CALL(_reset_state);
}
Error Resource::copy_from(const Ref<Resource> &p_resource) {
@@ -495,9 +497,9 @@ void Resource::set_as_translation_remapped(bool p_remapped) {
}
}
-#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void Resource::set_id_for_path(const String &p_path, const String &p_id) {
+#ifdef TOOLS_ENABLED
if (p_id.is_empty()) {
ResourceCache::path_cache_lock.write_lock();
ResourceCache::resource_path_cache[p_path].erase(get_path());
@@ -507,9 +509,11 @@ void Resource::set_id_for_path(const String &p_path, const String &p_id) {
ResourceCache::resource_path_cache[p_path][get_path()] = p_id;
ResourceCache::path_cache_lock.write_unlock();
}
+#endif
}
String Resource::get_id_for_path(const String &p_path) const {
+#ifdef TOOLS_ENABLED
ResourceCache::path_cache_lock.read_lock();
if (ResourceCache::resource_path_cache[p_path].has(get_path())) {
String result = ResourceCache::resource_path_cache[p_path][get_path()];
@@ -519,13 +523,16 @@ String Resource::get_id_for_path(const String &p_path) const {
ResourceCache::path_cache_lock.read_unlock();
return "";
}
-}
+#else
+ return "";
#endif
+}
void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path", "path"), &Resource::_set_path);
ClassDB::bind_method(D_METHOD("take_over_path", "path"), &Resource::_take_over_path);
ClassDB::bind_method(D_METHOD("get_path"), &Resource::get_path);
+ ClassDB::bind_method(D_METHOD("set_path_cache", "path"), &Resource::set_path_cache);
ClassDB::bind_method(D_METHOD("set_name", "name"), &Resource::set_name);
ClassDB::bind_method(D_METHOD("get_name"), &Resource::get_name);
ClassDB::bind_method(D_METHOD("get_rid"), &Resource::get_rid);
@@ -533,6 +540,12 @@ void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_local_to_scene"), &Resource::is_local_to_scene);
ClassDB::bind_method(D_METHOD("get_local_scene"), &Resource::get_local_scene);
ClassDB::bind_method(D_METHOD("setup_local_to_scene"), &Resource::setup_local_to_scene);
+ ClassDB::bind_method(D_METHOD("reset_state"), &Resource::reset_state);
+
+ ClassDB::bind_method(D_METHOD("set_id_for_path", "path", "id"), &Resource::set_id_for_path);
+ ClassDB::bind_method(D_METHOD("get_id_for_path", "path"), &Resource::get_id_for_path);
+
+ ClassDB::bind_method(D_METHOD("is_built_in"), &Resource::is_built_in);
ClassDB::bind_static_method("Resource", D_METHOD("generate_scene_unique_id"), &Resource::generate_scene_unique_id);
ClassDB::bind_method(D_METHOD("set_scene_unique_id", "id"), &Resource::set_scene_unique_id);
@@ -552,6 +565,8 @@ void Resource::_bind_methods() {
GDVIRTUAL_BIND(_setup_local_to_scene);
GDVIRTUAL_BIND(_get_rid);
+ GDVIRTUAL_BIND(_reset_state);
+ GDVIRTUAL_BIND(_set_path_cache, "path");
}
Resource::Resource() :
diff --git a/core/io/resource.h b/core/io/resource.h
index 2c1a431255..8966c0233c 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -89,6 +89,9 @@ protected:
GDVIRTUAL0RC(RID, _get_rid);
+ GDVIRTUAL1C(_set_path_cache, String);
+ GDVIRTUAL0(_reset_state);
+
public:
static Node *(*_get_local_scene_func)(); //used by editor
static void (*_update_configuration_warning)(); //used by editor
@@ -144,11 +147,9 @@ public:
virtual RID get_rid() const; // some resources may offer conversion to RID
-#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
void set_id_for_path(const String &p_path, const String &p_id);
String get_id_for_path(const String &p_path) const;
-#endif
Resource();
~Resource();
diff --git a/core/variant/variant_op.h b/core/variant/variant_op.h
index ac39a4135f..0bd8b830e0 100644
--- a/core/variant/variant_op.h
+++ b/core/variant/variant_op.h
@@ -923,7 +923,10 @@ public:
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
bool valid = true;
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), &valid);
- ERR_FAIL_COND_MSG(!valid, result);
+ if (unlikely(!valid)) {
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
+ ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
+ }
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
@@ -948,7 +951,10 @@ public:
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
bool valid = true;
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), &valid);
- ERR_FAIL_COND_MSG(!valid, result);
+ if (unlikely(!valid)) {
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
+ ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
+ }
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
@@ -976,7 +982,10 @@ public:
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
bool valid = true;
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), right->get_validated_object(), &valid);
- ERR_FAIL_COND_MSG(!valid, result);
+ if (unlikely(!valid)) {
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
+ ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
+ }
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
@@ -1003,7 +1012,10 @@ public:
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
bool valid = true;
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), &valid);
- ERR_FAIL_COND_MSG(!valid, result);
+ if (unlikely(!valid)) {
+ *VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
+ ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
+ }
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
}
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
@@ -1492,7 +1504,10 @@ public:
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *l = right->get_validated_object();
- ERR_FAIL_NULL(l);
+ if (unlikely(!l)) {
+ *VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
+ ERR_FAIL_MSG("Invalid base object for 'in'.");
+ }
const String &a = *VariantGetInternalPtr<String>::get_ptr(left);
bool valid;
@@ -1526,7 +1541,10 @@ public:
}
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *l = right->get_validated_object();
- ERR_FAIL_NULL(l);
+ if (unlikely(!l)) {
+ *VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
+ ERR_FAIL_MSG("Invalid base object for 'in'.");
+ }
const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left);
bool valid;
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index f222cbc969..a86f41cd9c 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -856,7 +856,7 @@
GD.Print("a", "b", a); // Prints ab[1, 2, 3]
[/csharp]
[/codeblocks]
- [b]Note:[/b] Consider using [method push_error] and [method push_warning] to print error and warning messages instead of [method print] or [method print_rich]. This distinguishes them from print messages used for debugging purposes, while also displaying a stack trace when an error or warning is printed.
+ [b]Note:[/b] Consider using [method push_error] and [method push_warning] to print error and warning messages instead of [method print] or [method print_rich]. This distinguishes them from print messages used for debugging purposes, while also displaying a stack trace when an error or warning is printed. See also [member Engine.print_to_stdout] and [member ProjectSettings.application/run/disable_stdout].
</description>
</method>
<method name="print_rich" qualifiers="vararg">
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 764f4a65b5..18dccfa5a9 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -57,7 +57,7 @@
</member>
<member name="button_pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false">
If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). Only works if [member toggle_mode] is [code]true[/code].
- [b]Note:[/b] Setting [member button_pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal].
+ [b]Note:[/b] Changing the value of [member button_pressed] will result in [signal toggled] to be emitted. If you want to change the pressed state without emitting that signal, use [method set_pressed_no_signal].
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled" default="false" keywords="enabled">
If [code]true[/code], the button is in disabled state and can't be clicked or toggled.
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 0a0223c550..423059a0c7 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -528,6 +528,7 @@
<description>
Returns [code]true[/code] if the node is present in the [SceneTree], its [member visible] property is [code]true[/code] and all its ancestors are also visible. If any ancestor is hidden, this node will not be visible in the scene tree, and is therefore not drawn (see [method _draw]).
Visibility is checked only in parent nodes that inherit from [CanvasItem], [CanvasLayer], and [Window]. If the parent is of any other type (such as [Node], [AnimationPlayer], or [Node3D]), it is assumed to be visible.
+ [b]Note:[/b] This method does not take [member visibility_layer] into account, so even if this method returns [code]true[/code] the node might end up not being rendered.
</description>
</method>
<method name="make_canvas_position_local" qualifiers="const">
@@ -622,7 +623,7 @@
The rendering layer in which this [CanvasItem] is rendered by [Viewport] nodes. A [Viewport] will render a [CanvasItem] if it and all its parents share a layer with the [Viewport]'s canvas cull mask.
</member>
<member name="visible" type="bool" setter="set_visible" getter="is_visible" default="true">
- If [code]true[/code], this [CanvasItem] is drawn. The node is only visible if all of its ancestors are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]).
+ If [code]true[/code], this [CanvasItem] may be drawn. Whether this [CanvasItem] is actually drawn depends on the visibility of all of its [CanvasItem] ancestors. In other words: this [CanvasItem] will be drawn when [method is_visible_in_tree] returns [code]true[/code] and all [CanvasItem] ancestors share at least one [member visibility_layer] with this [CanvasItem].
[b]Note:[/b] For controls that inherit [Popup], the correct way to make them visible is to call one of the multiple [code]popup*()[/code] functions instead.
</member>
<member name="y_sort_enabled" type="bool" setter="set_y_sort_enabled" getter="is_y_sort_enabled" default="false">
@@ -647,17 +648,17 @@
</signal>
<signal name="hidden">
<description>
- Emitted when becoming hidden.
+ Emitted when the [CanvasItem] becomes hidden, either because its own [member visible] property was set to [code]false[/code] or the [member visible] property of one of its [CanvasItem] ancestors was set to [code]false[/code].
</description>
</signal>
<signal name="item_rect_changed">
<description>
- Emitted when the item's [Rect2] boundaries (position or size) have changed, or when an action is taking place that may have impacted these boundaries (e.g. changing [member Sprite2D.texture]).
+ Emitted when the [CanvasItem]'s boundaries (position or size) change, or when an action took place that may have affected these boundaries (e.g. changing [member Sprite2D.texture]).
</description>
</signal>
<signal name="visibility_changed">
<description>
- Emitted when the visibility (hidden/visible) changes.
+ Emitted when the [CanvasItem]'s visibility changes, either because its own [member visible] property changed or because the visility of one of its [CanvasItem] ancestors changed (equivalent to a change in [method is_visible_in_tree]).
</description>
</signal>
</signals>
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 940fec4688..5eb8ac6199 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -1200,6 +1200,9 @@
<member name="text_editor/behavior/files/trim_trailing_whitespace_on_save" type="bool" setter="" getter="">
If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy.
</member>
+ <member name="text_editor/behavior/general/empty_selection_clipboard" type="bool" setter="" getter="">
+ If [code]true[/code], copying or cutting without a selection is performed on all lines with a caret. Otherwise, copy and cut require a selection.
+ </member>
<member name="text_editor/behavior/indent/auto_indent" type="bool" setter="" getter="">
If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line.
</member>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index ca78054875..bba5157053 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -337,6 +337,10 @@
[b]Note:[/b] This property does not impact the editor's Errors tab when running a project from the editor.
[b]Warning:[/b] If set to [code]false[/code] anywhere in the project, important error messages may be hidden even if they are emitted from other scripts. In a [code]@tool[/code] script, this will also impact the editor itself. Do [i]not[/i] report bugs before ensuring error messages are enabled (as they are by default).
</member>
+ <member name="print_to_stdout" type="bool" setter="set_print_to_stdout" getter="is_printing_to_stdout" default="true">
+ If [code]false[/code], stops printing messages (for example using [method @GlobalScope.print]) to the console, log files, and editor Output log. This property is equivalent to the [member ProjectSettings.application/run/disable_stdout] project setting.
+ [b]Note:[/b] This does not stop printing errors or warnings produced by scripts to the console or log files, for more details see [member print_error_messages].
+ </member>
<member name="time_scale" type="float" setter="set_time_scale" getter="get_time_scale" default="1.0">
The speed multiplier at which the in-game clock updates, compared to real time. For example, if set to [code]2.0[/code] the game runs twice as fast, and if set to [code]0.5[/code] the game runs half as fast.
This value affects [Timer], [SceneTreeTimer], and all other simulations that make use of [code]delta[/code] time (such as [method Node._process] and [method Node._physics_process]).
diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml
index 494e9966ac..ec0300c068 100644
--- a/doc/classes/PCKPacker.xml
+++ b/doc/classes/PCKPacker.xml
@@ -42,12 +42,12 @@
</method>
<method name="pck_start">
<return type="int" enum="Error" />
- <param index="0" name="pck_name" type="String" />
+ <param index="0" name="pck_path" type="String" />
<param index="1" name="alignment" type="int" default="32" />
<param index="2" name="key" type="String" default="&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;" />
<param index="3" name="encrypt_directory" type="bool" default="false" />
<description>
- Creates a new PCK file with the name [param pck_name]. The [code].pck[/code] file extension isn't added automatically, so it should be part of [param pck_name] (even though it's not required).
+ Creates a new PCK file at the file path [param pck_path]. The [code].pck[/code] file extension isn't added automatically, so it should be part of [param pck_path] (even though it's not required).
</description>
</method>
</methods>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 758e98ad85..0e5097b7b2 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -314,11 +314,11 @@
</member>
<member name="application/run/disable_stderr" type="bool" setter="" getter="" default="false">
If [code]true[/code], disables printing to standard error. If [code]true[/code], this also hides error and warning messages printed by [method @GlobalScope.push_error] and [method @GlobalScope.push_warning]. See also [member application/run/disable_stdout].
- Changes to this setting will only be applied upon restarting the application.
+ Changes to this setting will only be applied upon restarting the application. To control this at runtime, use [member Engine.print_error_messages].
</member>
<member name="application/run/disable_stdout" type="bool" setter="" getter="" default="false">
If [code]true[/code], disables printing to standard output. This is equivalent to starting the editor or project with the [code]--quiet[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. See also [member application/run/disable_stderr].
- Changes to this setting will only be applied upon restarting the application.
+ Changes to this setting will only be applied upon restarting the application. To control this at runtime, use [member Engine.print_to_stdout].
</member>
<member name="application/run/enable_alt_space_menu" type="bool" setter="" getter="" default="false">
If [code]true[/code], allows the [kbd]Alt + Space[/kbd] keys to display the window menu. This menu allows the user to perform various window management operations such as moving, resizing, or minimizing the window.
@@ -2293,6 +2293,7 @@
<member name="physics/3d/physics_engine" type="String" setter="" getter="" default="&quot;DEFAULT&quot;">
Sets which physics engine to use for 3D physics.
"DEFAULT" and "GodotPhysics3D" are the same, as there is currently no alternative 3D physics server implemented.
+ "Dummy" is a 3D physics server that does nothing and returns only dummy values, effectively disabling all 3D physics functionality.
</member>
<member name="physics/3d/run_on_separate_thread" type="bool" setter="" getter="" default="false">
If [code]true[/code], the 3D physics server runs on a separate thread, making better use of multi-core CPUs. If [code]false[/code], the 3D physics server runs on the main thread. Running the physics server on a separate thread can increase performance, but restricts API access to only physics process.
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index fe09472c14..18d4047339 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -20,6 +20,19 @@
Override this method to return a custom [RID] when [method get_rid] is called.
</description>
</method>
+ <method name="_reset_state" qualifiers="virtual">
+ <return type="void" />
+ <description>
+ For resources that use a variable number of properties, either via [method Object._validate_property] or [method Object._get_property_list], this method should be implemented to correctly clear the resource's state.
+ </description>
+ </method>
+ <method name="_set_path_cache" qualifiers="virtual const">
+ <return type="void" />
+ <param index="0" name="path" type="String" />
+ <description>
+ Sets the resource's path to [param path] without involving the resource cache.
+ </description>
+ </method>
<method name="_setup_local_to_scene" qualifiers="virtual">
<return type="void" />
<description>
@@ -68,6 +81,14 @@
Generates a unique identifier for a resource to be contained inside a [PackedScene], based on the current date, time, and a random value. The returned string is only composed of letters ([code]a[/code] to [code]y[/code]) and numbers ([code]0[/code] to [code]8[/code]). See also [member resource_scene_unique_id].
</description>
</method>
+ <method name="get_id_for_path" qualifiers="const">
+ <return type="String" />
+ <param index="0" name="path" type="String" />
+ <description>
+ Returns the unique identifier for the resource with the given [param path] from the resource cache. If the resource is not loaded and cached, an empty string is returned.
+ [b]Note:[/b] This method is only implemented when running in an editor context. At runtime, it returns an empty string.
+ </description>
+ </method>
<method name="get_local_scene" qualifiers="const">
<return type="Node" />
<description>
@@ -80,6 +101,34 @@
Returns the [RID] of this resource (or an empty RID). Many resources (such as [Texture2D], [Mesh], and so on) are high-level abstractions of resources stored in a specialized server ([DisplayServer], [RenderingServer], etc.), so this function will return the original [RID].
</description>
</method>
+ <method name="is_built_in" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the resource is built-in (from the engine) or [code]false[/code] if it is user-defined.
+ </description>
+ </method>
+ <method name="reset_state">
+ <return type="void" />
+ <description>
+ For resources that use a variable number of properties, either via [method Object._validate_property] or [method Object._get_property_list], override [method _reset_state] to correctly clear the resource's state.
+ </description>
+ </method>
+ <method name="set_id_for_path">
+ <return type="void" />
+ <param index="0" name="path" type="String" />
+ <param index="1" name="id" type="String" />
+ <description>
+ Sets the unique identifier to [param id] for the resource with the given [param path] in the resource cache. If the unique identifier is empty, the cache entry using [param path] is removed if it exists.
+ [b]Note:[/b] This method is only implemented when running in an editor context.
+ </description>
+ </method>
+ <method name="set_path_cache">
+ <return type="void" />
+ <param index="0" name="path" type="String" />
+ <description>
+ Sets the resource's path to [param path] without involving the resource cache.
+ </description>
+ </method>
<method name="setup_local_to_scene" deprecated="This method should only be called internally.">
<return type="void" />
<description>
diff --git a/doc/classes/ResourceSaver.xml b/doc/classes/ResourceSaver.xml
index 42c9bd7a3c..05c749bc24 100644
--- a/doc/classes/ResourceSaver.xml
+++ b/doc/classes/ResourceSaver.xml
@@ -26,6 +26,14 @@
Returns the list of extensions available for saving a resource of a given type.
</description>
</method>
+ <method name="get_resource_id_for_path">
+ <return type="int" />
+ <param index="0" name="path" type="String" />
+ <param index="1" name="generate" type="bool" default="false" />
+ <description>
+ Returns the resource ID for the given path. If [param generate] is [code]true[/code], a new resource ID will be generated if one for the path is not found. If [param generate] is [code]false[/code] and the path is not found, [constant ResourceUID.INVALID_ID] is returned.
+ </description>
+ </method>
<method name="remove_resource_format_saver">
<return type="void" />
<param index="0" name="format_saver" type="ResourceFormatSaver" />
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index 9fada9db35..42558bf992 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1299,6 +1299,9 @@
<member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true" keywords="readonly, disabled, enabled">
If [code]false[/code], existing text cannot be modified and new text cannot be added.
</member>
+ <member name="empty_selection_clipboard_enabled" type="bool" setter="set_empty_selection_clipboard_enabled" getter="is_empty_selection_clipboard_enabled" default="true">
+ If [code]true[/code], copying or cutting without a selection is performed on all lines with a caret. Otherwise, copy and cut require a selection.
+ </member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled" default="false">
If [code]true[/code], all occurrences of the selected text will be highlighted.
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 101660881b..e1a6aa4a98 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -150,7 +150,7 @@ PACKED_ARRAY_TYPES: List[str] = [
"PackedByteArray",
"PackedColorArray",
"PackedFloat32Array",
- "Packedfloat64Array",
+ "PackedFloat64Array",
"PackedInt32Array",
"PackedInt64Array",
"PackedStringArray",
@@ -949,13 +949,17 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir:
inherits = class_def.inherits.strip()
f.write(f'**{translate("Inherits:")}** ')
first = True
- while inherits in state.classes:
+ while inherits is not None:
if not first:
f.write(" **<** ")
else:
first = False
f.write(make_type(inherits, state))
+
+ if inherits not in state.classes:
+ break # Parent unknown.
+
inode = state.classes[inherits].inherits
if inode:
inherits = inode.strip()
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index d97293329a..40b58d2c62 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -1090,6 +1090,9 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_draw_spaces(EDITOR_GET("text_editor/appearance/whitespace/draw_spaces"));
text_editor->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
+ // Behavior: General
+ text_editor->set_empty_selection_clipboard_enabled(EDITOR_GET("text_editor/behavior/general/empty_selection_clipboard"));
+
// Behavior: Navigation
text_editor->set_scroll_past_end_of_file_enabled(EDITOR_GET("text_editor/behavior/navigation/scroll_past_end_of_file"));
text_editor->set_smooth_scroll_enabled(EDITOR_GET("text_editor/behavior/navigation/smooth_scrolling"));
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index bc7bfcfa58..27cbb9810c 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -30,10 +30,12 @@
#include "editor_sectioned_inspector.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/themes/editor_scale.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/tree.h"
static bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) {
if (p_property_path.containsn(p_filter)) {
@@ -307,18 +309,35 @@ void SectionedInspector::register_search_box(LineEdit *p_box) {
search_box->connect(SceneStringName(text_changed), callable_mp(this, &SectionedInspector::_search_changed));
}
+void SectionedInspector::register_advanced_toggle(CheckButton *p_toggle) {
+ advanced_toggle = p_toggle;
+ advanced_toggle->connect(SceneStringName(toggled), callable_mp(this, &SectionedInspector::_advanced_toggled));
+ _advanced_toggled(advanced_toggle->is_pressed());
+}
+
void SectionedInspector::_search_changed(const String &p_what) {
+ if (advanced_toggle) {
+ if (p_what.is_empty()) {
+ advanced_toggle->set_pressed_no_signal(!restrict_to_basic);
+ advanced_toggle->set_disabled(false);
+ advanced_toggle->set_tooltip_text(String());
+ } else {
+ advanced_toggle->set_pressed_no_signal(true);
+ advanced_toggle->set_disabled(true);
+ advanced_toggle->set_tooltip_text(TTR("Advanced settings are always shown when searching."));
+ }
+ }
update_category_list();
}
-EditorInspector *SectionedInspector::get_inspector() {
- return inspector;
+void SectionedInspector::_advanced_toggled(bool p_toggled_on) {
+ restrict_to_basic = !p_toggled_on;
+ update_category_list();
+ inspector->set_restrict_to_basic_settings(restrict_to_basic);
}
-void SectionedInspector::set_restrict_to_basic_settings(bool p_restrict) {
- restrict_to_basic = p_restrict;
- update_category_list();
- inspector->set_restrict_to_basic_settings(p_restrict);
+EditorInspector *SectionedInspector::get_inspector() {
+ return inspector;
}
SectionedInspector::SectionedInspector() :
diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h
index 3c9eb78571..75f1569d36 100644
--- a/editor/editor_sectioned_inspector.h
+++ b/editor/editor_sectioned_inspector.h
@@ -31,11 +31,14 @@
#ifndef EDITOR_SECTIONED_INSPECTOR_H
#define EDITOR_SECTIONED_INSPECTOR_H
-#include "editor/editor_inspector.h"
#include "scene/gui/split_container.h"
-#include "scene/gui/tree.h"
+class CheckButton;
+class EditorInspector;
+class LineEdit;
class SectionedInspectorFilter;
+class Tree;
+class TreeItem;
class SectionedInspector : public HSplitContainer {
GDCLASS(SectionedInspector, HSplitContainer);
@@ -48,6 +51,7 @@ class SectionedInspector : public HSplitContainer {
HashMap<String, TreeItem *> section_map;
EditorInspector *inspector = nullptr;
LineEdit *search_box = nullptr;
+ CheckButton *advanced_toggle = nullptr;
String selected_category;
@@ -57,9 +61,12 @@ class SectionedInspector : public HSplitContainer {
void _section_selected();
void _search_changed(const String &p_what);
+ void _advanced_toggled(bool p_toggled_on);
public:
void register_search_box(LineEdit *p_box);
+ void register_advanced_toggle(CheckButton *p_toggle);
+
EditorInspector *get_inspector();
void edit(Object *p_object);
String get_full_item_path(const String &p_item);
@@ -67,7 +74,6 @@ public:
void set_current_section(const String &p_section);
String get_current_section() const;
- void set_restrict_to_basic_settings(bool p_restrict);
void update_category_list();
SectionedInspector();
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 963c45b573..c972a6ab27 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -668,6 +668,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/whitespace/line_spacing", 4, "0,50,1")
// Behavior
+ // Behavior: General
+ _initial_set("text_editor/behavior/general/empty_selection_clipboard", true);
+
// Behavior: Navigation
_initial_set("text_editor/behavior/navigation/move_caret_on_right_click", true, true);
_initial_set("text_editor/behavior/navigation/scroll_past_end_of_file", false, true);
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index b133847823..d07608d852 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -33,6 +33,7 @@
#include "core/input/input_map.h"
#include "core/os/keyboard.h"
#include "editor/debugger/editor_debugger_node.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
@@ -806,7 +807,6 @@ void EditorSettingsDialog::_focus_current_search_box() {
void EditorSettingsDialog::_advanced_toggled(bool p_button_pressed) {
EditorSettings::get_singleton()->set("_editor_settings_advanced_mode", p_button_pressed);
- inspector->set_restrict_to_basic_settings(!p_button_pressed);
}
void EditorSettingsDialog::_editor_restart() {
@@ -860,8 +860,8 @@ EditorSettingsDialog::EditorSettingsDialog() {
inspector = memnew(SectionedInspector);
inspector->get_inspector()->set_use_filter(true);
- inspector->set_restrict_to_basic_settings(!use_advanced);
inspector->register_search_box(search_box);
+ inspector->register_advanced_toggle(advanced_switch);
inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tab_general->add_child(inspector);
inspector->get_inspector()->connect("property_edited", callable_mp(this, &EditorSettingsDialog::_settings_property_edited));
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index ce2dbe7cb1..e0de6bbcb1 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -840,7 +840,7 @@ GroupsEditor::GroupsEditor() {
add_child(hbc);
add = memnew(Button);
- add->set_flat(true);
+ add->set_theme_type_variation("FlatMenuButton");
add->set_tooltip_text(TTR("Add a new group."));
add->connect(SceneStringName(pressed), callable_mp(this, &GroupsEditor::_show_add_group_dialog));
hbc->add_child(add);
diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
index 31e3022f6b..23e803f722 100644
--- a/editor/import_defaults_editor.cpp
+++ b/editor/import_defaults_editor.cpp
@@ -33,11 +33,8 @@
#include "core/config/project_settings.h"
#include "core/io/resource_importer.h"
#include "editor/action_map_editor.h"
-#include "editor/editor_autoload_settings.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_sectioned_inspector.h"
-#include "editor/localization_editor.h"
-#include "editor/plugins/editor_plugin_settings.h"
-#include "editor/shader_globals_editor.h"
#include "scene/gui/center_container.h"
class ImportDefaultsEditorSettings : public Object {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index d00fdc2123..5767293718 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -31,7 +31,7 @@
#include "project_settings_editor.h"
#include "core/config/project_settings.h"
-#include "editor/editor_log.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
@@ -106,7 +106,6 @@ void ProjectSettingsEditor::_update_advanced(bool p_is_advanced) {
void ProjectSettingsEditor::_advanced_toggled(bool p_button_pressed) {
EditorSettings::get_singleton()->set_project_metadata("project_settings", "advanced_mode", p_button_pressed);
_update_advanced(p_button_pressed);
- general_settings_inspector->set_restrict_to_basic_settings(!p_button_pressed);
}
void ProjectSettingsEditor::_setting_selected(const String &p_path) {
@@ -688,6 +687,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
general_settings_inspector = memnew(SectionedInspector);
general_settings_inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
general_settings_inspector->register_search_box(search_box);
+ general_settings_inspector->register_advanced_toggle(advanced);
general_settings_inspector->get_inspector()->set_use_filter(true);
general_settings_inspector->get_inspector()->connect("property_selected", callable_mp(this, &ProjectSettingsEditor::_setting_selected));
general_settings_inspector->get_inspector()->connect("property_edited", callable_mp(this, &ProjectSettingsEditor::_setting_edited));
@@ -771,11 +771,10 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
bool use_advanced = EditorSettings::get_singleton()->get_project_metadata("project_settings", "advanced_mode", false);
if (use_advanced) {
- advanced->set_pressed_no_signal(true);
+ advanced->set_pressed(true);
}
_update_advanced(use_advanced);
- general_settings_inspector->set_restrict_to_basic_settings(!use_advanced);
import_defaults_editor = memnew(ImportDefaultsEditor);
import_defaults_editor->set_name(TTR("Import Defaults"));
diff --git a/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index c05f60545d..85e5cd6ea0 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -31,6 +31,7 @@
#include "shader_globals_editor.h"
#include "core/config/project_settings.h"
+#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
#include "editor/editor_undo_redo_manager.h"
#include "servers/rendering/shader_language.h"
diff --git a/main/main.cpp b/main/main.cpp
index fa50a3039f..439cd385c0 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -83,6 +83,7 @@
#ifndef _3D_DISABLED
#include "servers/physics_server_3d.h"
+#include "servers/physics_server_3d_dummy.h"
#include "servers/xr_server.h"
#endif // _3D_DISABLED
@@ -320,7 +321,15 @@ void initialize_physics() {
// Physics server not found, Use the default physics
physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server();
}
- ERR_FAIL_NULL(physics_server_3d);
+
+ // Fall back to dummy if no default server has been registered.
+ if (!physics_server_3d) {
+ WARN_PRINT(vformat("Falling back to dummy PhysicsServer3D; 3D physics functionality will be disabled. If this is intended, set the %s project setting to Dummy.", PhysicsServer3DManager::setting_property_name));
+ physics_server_3d = memnew(PhysicsServer3DDummy);
+ }
+
+ // Should be impossible, but make sure it's not null.
+ ERR_FAIL_NULL_MSG(physics_server_3d, "Failed to initialize PhysicsServer3D.");
physics_server_3d->init();
#endif // _3D_DISABLED
diff --git a/modules/godot_physics_3d/SCsub b/modules/godot_physics_3d/SCsub
new file mode 100644
index 0000000000..41a59cd24e
--- /dev/null
+++ b/modules/godot_physics_3d/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import('env')
+
+env.add_source_files(env.modules_sources, "*.cpp")
+
+SConscript("joints/SCsub")
diff --git a/modules/godot_physics_3d/config.py b/modules/godot_physics_3d/config.py
new file mode 100644
index 0000000000..a42f27fbe1
--- /dev/null
+++ b/modules/godot_physics_3d/config.py
@@ -0,0 +1,6 @@
+def can_build(env, platform):
+ return not env["disable_3d"]
+
+
+def configure(env):
+ pass
diff --git a/servers/physics_3d/gjk_epa.cpp b/modules/godot_physics_3d/gjk_epa.cpp
index e5678914fe..e5678914fe 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/modules/godot_physics_3d/gjk_epa.cpp
diff --git a/servers/physics_3d/gjk_epa.h b/modules/godot_physics_3d/gjk_epa.h
index 48fda9969f..48fda9969f 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/modules/godot_physics_3d/gjk_epa.h
diff --git a/servers/physics_3d/godot_area_3d.cpp b/modules/godot_physics_3d/godot_area_3d.cpp
index d0b287b058..d0b287b058 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/modules/godot_physics_3d/godot_area_3d.cpp
diff --git a/servers/physics_3d/godot_area_3d.h b/modules/godot_physics_3d/godot_area_3d.h
index 2c1a782630..2c1a782630 100644
--- a/servers/physics_3d/godot_area_3d.h
+++ b/modules/godot_physics_3d/godot_area_3d.h
diff --git a/servers/physics_3d/godot_area_pair_3d.cpp b/modules/godot_physics_3d/godot_area_pair_3d.cpp
index aaa96f5a28..aaa96f5a28 100644
--- a/servers/physics_3d/godot_area_pair_3d.cpp
+++ b/modules/godot_physics_3d/godot_area_pair_3d.cpp
diff --git a/servers/physics_3d/godot_area_pair_3d.h b/modules/godot_physics_3d/godot_area_pair_3d.h
index a2c5df0f7a..a2c5df0f7a 100644
--- a/servers/physics_3d/godot_area_pair_3d.h
+++ b/modules/godot_physics_3d/godot_area_pair_3d.h
diff --git a/servers/physics_3d/godot_body_3d.cpp b/modules/godot_physics_3d/godot_body_3d.cpp
index 669c4b985b..669c4b985b 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/modules/godot_physics_3d/godot_body_3d.cpp
diff --git a/servers/physics_3d/godot_body_3d.h b/modules/godot_physics_3d/godot_body_3d.h
index 81b668122a..81b668122a 100644
--- a/servers/physics_3d/godot_body_3d.h
+++ b/modules/godot_physics_3d/godot_body_3d.h
diff --git a/servers/physics_3d/godot_body_direct_state_3d.cpp b/modules/godot_physics_3d/godot_body_direct_state_3d.cpp
index 0af746c68d..0af746c68d 100644
--- a/servers/physics_3d/godot_body_direct_state_3d.cpp
+++ b/modules/godot_physics_3d/godot_body_direct_state_3d.cpp
diff --git a/servers/physics_3d/godot_body_direct_state_3d.h b/modules/godot_physics_3d/godot_body_direct_state_3d.h
index 8066050c9f..8066050c9f 100644
--- a/servers/physics_3d/godot_body_direct_state_3d.h
+++ b/modules/godot_physics_3d/godot_body_direct_state_3d.h
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/modules/godot_physics_3d/godot_body_pair_3d.cpp
index 84fae73616..84fae73616 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/modules/godot_physics_3d/godot_body_pair_3d.cpp
diff --git a/servers/physics_3d/godot_body_pair_3d.h b/modules/godot_physics_3d/godot_body_pair_3d.h
index a8f5180dd5..a8f5180dd5 100644
--- a/servers/physics_3d/godot_body_pair_3d.h
+++ b/modules/godot_physics_3d/godot_body_pair_3d.h
diff --git a/servers/physics_3d/godot_broad_phase_3d.cpp b/modules/godot_physics_3d/godot_broad_phase_3d.cpp
index ebd11fb51f..ebd11fb51f 100644
--- a/servers/physics_3d/godot_broad_phase_3d.cpp
+++ b/modules/godot_physics_3d/godot_broad_phase_3d.cpp
diff --git a/servers/physics_3d/godot_broad_phase_3d.h b/modules/godot_physics_3d/godot_broad_phase_3d.h
index f70321be64..f70321be64 100644
--- a/servers/physics_3d/godot_broad_phase_3d.h
+++ b/modules/godot_physics_3d/godot_broad_phase_3d.h
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/modules/godot_physics_3d/godot_broad_phase_3d_bvh.cpp
index 0faa56b52e..0faa56b52e 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp
+++ b/modules/godot_physics_3d/godot_broad_phase_3d_bvh.cpp
diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.h b/modules/godot_physics_3d/godot_broad_phase_3d_bvh.h
index 63968dea64..63968dea64 100644
--- a/servers/physics_3d/godot_broad_phase_3d_bvh.h
+++ b/modules/godot_physics_3d/godot_broad_phase_3d_bvh.h
diff --git a/servers/physics_3d/godot_collision_object_3d.cpp b/modules/godot_physics_3d/godot_collision_object_3d.cpp
index 283614a43d..283614a43d 100644
--- a/servers/physics_3d/godot_collision_object_3d.cpp
+++ b/modules/godot_physics_3d/godot_collision_object_3d.cpp
diff --git a/servers/physics_3d/godot_collision_object_3d.h b/modules/godot_physics_3d/godot_collision_object_3d.h
index bf28bcc45a..bf28bcc45a 100644
--- a/servers/physics_3d/godot_collision_object_3d.h
+++ b/modules/godot_physics_3d/godot_collision_object_3d.h
diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/modules/godot_physics_3d/godot_collision_solver_3d.cpp
index db48111eea..db48111eea 100644
--- a/servers/physics_3d/godot_collision_solver_3d.cpp
+++ b/modules/godot_physics_3d/godot_collision_solver_3d.cpp
diff --git a/servers/physics_3d/godot_collision_solver_3d.h b/modules/godot_physics_3d/godot_collision_solver_3d.h
index 36ea79576e..36ea79576e 100644
--- a/servers/physics_3d/godot_collision_solver_3d.h
+++ b/modules/godot_physics_3d/godot_collision_solver_3d.h
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp
index c53c8481f4..c53c8481f4 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.h b/modules/godot_physics_3d/godot_collision_solver_3d_sat.h
index 49fcab3933..49fcab3933 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.h
+++ b/modules/godot_physics_3d/godot_collision_solver_3d_sat.h
diff --git a/servers/physics_3d/godot_constraint_3d.h b/modules/godot_physics_3d/godot_constraint_3d.h
index a833aba93f..a833aba93f 100644
--- a/servers/physics_3d/godot_constraint_3d.h
+++ b/modules/godot_physics_3d/godot_constraint_3d.h
diff --git a/servers/physics_3d/godot_joint_3d.h b/modules/godot_physics_3d/godot_joint_3d.h
index 3207723cb4..3207723cb4 100644
--- a/servers/physics_3d/godot_joint_3d.h
+++ b/modules/godot_physics_3d/godot_joint_3d.h
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/modules/godot_physics_3d/godot_physics_server_3d.cpp
index 8a7b4e0f07..6d0949acbe 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/modules/godot_physics_3d/godot_physics_server_3d.cpp
@@ -1629,8 +1629,6 @@ void GodotPhysicsServer3D::init() {
}
void GodotPhysicsServer3D::step(real_t p_step) {
-#ifndef _3D_DISABLED
-
if (!active) {
return;
}
@@ -1646,7 +1644,6 @@ void GodotPhysicsServer3D::step(real_t p_step) {
active_objects += E->get_active_objects();
collision_pairs += E->get_collision_pairs();
}
-#endif
}
void GodotPhysicsServer3D::sync() {
@@ -1654,8 +1651,6 @@ void GodotPhysicsServer3D::sync() {
}
void GodotPhysicsServer3D::flush_queries() {
-#ifndef _3D_DISABLED
-
if (!active) {
return;
}
@@ -1703,7 +1698,6 @@ void GodotPhysicsServer3D::flush_queries() {
values.push_front("physics_3d");
EngineDebugger::profiler_add_frame_data("servers", values);
}
-#endif
}
void GodotPhysicsServer3D::end_sync() {
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/modules/godot_physics_3d/godot_physics_server_3d.h
index 040e673dcd..040e673dcd 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/modules/godot_physics_3d/godot_physics_server_3d.h
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/modules/godot_physics_3d/godot_shape_3d.cpp
index 70b6bcf19e..70b6bcf19e 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/modules/godot_physics_3d/godot_shape_3d.cpp
diff --git a/servers/physics_3d/godot_shape_3d.h b/modules/godot_physics_3d/godot_shape_3d.h
index dbd58ead68..dbd58ead68 100644
--- a/servers/physics_3d/godot_shape_3d.h
+++ b/modules/godot_physics_3d/godot_shape_3d.h
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/modules/godot_physics_3d/godot_soft_body_3d.cpp
index 7284076a47..7284076a47 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/modules/godot_physics_3d/godot_soft_body_3d.cpp
diff --git a/servers/physics_3d/godot_soft_body_3d.h b/modules/godot_physics_3d/godot_soft_body_3d.h
index e23f4bb9f5..e23f4bb9f5 100644
--- a/servers/physics_3d/godot_soft_body_3d.h
+++ b/modules/godot_physics_3d/godot_soft_body_3d.h
diff --git a/servers/physics_3d/godot_space_3d.cpp b/modules/godot_physics_3d/godot_space_3d.cpp
index 9a6ba776b4..9a6ba776b4 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/modules/godot_physics_3d/godot_space_3d.cpp
diff --git a/servers/physics_3d/godot_space_3d.h b/modules/godot_physics_3d/godot_space_3d.h
index f476be5934..f476be5934 100644
--- a/servers/physics_3d/godot_space_3d.h
+++ b/modules/godot_physics_3d/godot_space_3d.h
diff --git a/servers/physics_3d/godot_step_3d.cpp b/modules/godot_physics_3d/godot_step_3d.cpp
index d09a3b4e6d..d09a3b4e6d 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/modules/godot_physics_3d/godot_step_3d.cpp
diff --git a/servers/physics_3d/godot_step_3d.h b/modules/godot_physics_3d/godot_step_3d.h
index 1c9b0af422..1c9b0af422 100644
--- a/servers/physics_3d/godot_step_3d.h
+++ b/modules/godot_physics_3d/godot_step_3d.h
diff --git a/modules/godot_physics_3d/joints/SCsub b/modules/godot_physics_3d/joints/SCsub
new file mode 100644
index 0000000000..5d93da5ecf
--- /dev/null
+++ b/modules/godot_physics_3d/joints/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import('env')
+
+env.add_source_files(env.modules_sources, "*.cpp")
diff --git a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
index 4091422789..4091422789 100644
--- a/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp
+++ b/modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
diff --git a/servers/physics_3d/joints/godot_cone_twist_joint_3d.h b/modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h
index 8b749e4914..f3b683a8f3 100644
--- a/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
+++ b/modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h
@@ -52,8 +52,8 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-#include "servers/physics_3d/godot_joint_3d.h"
-#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
+#include "../godot_joint_3d.h"
+#include "godot_jacobian_entry_3d.h"
// GodotConeTwistJoint3D can be used to simulate ragdoll joints (upper arm, leg etc).
class GodotConeTwistJoint3D : public GodotJoint3D {
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp
index 226f8a0f7f..226f8a0f7f 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
+++ b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h
index 69a5266438..9ee6dd2791 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
+++ b/modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h
@@ -35,8 +35,8 @@
Adapted to Godot from the Bullet library.
*/
-#include "servers/physics_3d/godot_joint_3d.h"
-#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
+#include "../godot_joint_3d.h"
+#include "godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
diff --git a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp
index 3d423f70e2..3d423f70e2 100644
--- a/servers/physics_3d/joints/godot_hinge_joint_3d.cpp
+++ b/modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp
diff --git a/servers/physics_3d/joints/godot_hinge_joint_3d.h b/modules/godot_physics_3d/joints/godot_hinge_joint_3d.h
index eab60c1909..7f83509468 100644
--- a/servers/physics_3d/joints/godot_hinge_joint_3d.h
+++ b/modules/godot_physics_3d/joints/godot_hinge_joint_3d.h
@@ -35,8 +35,8 @@
Adapted to Godot from the Bullet library.
*/
-#include "servers/physics_3d/godot_joint_3d.h"
-#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
+#include "../godot_joint_3d.h"
+#include "godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
diff --git a/servers/physics_3d/joints/godot_jacobian_entry_3d.h b/modules/godot_physics_3d/joints/godot_jacobian_entry_3d.h
index d0c3c48ae6..d0c3c48ae6 100644
--- a/servers/physics_3d/joints/godot_jacobian_entry_3d.h
+++ b/modules/godot_physics_3d/joints/godot_jacobian_entry_3d.h
diff --git a/servers/physics_3d/joints/godot_pin_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp
index 05ae0839e4..05ae0839e4 100644
--- a/servers/physics_3d/joints/godot_pin_joint_3d.cpp
+++ b/modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp
diff --git a/servers/physics_3d/joints/godot_pin_joint_3d.h b/modules/godot_physics_3d/joints/godot_pin_joint_3d.h
index 2d19bcb626..62d3068e09 100644
--- a/servers/physics_3d/joints/godot_pin_joint_3d.h
+++ b/modules/godot_physics_3d/joints/godot_pin_joint_3d.h
@@ -35,8 +35,8 @@
Adapted to Godot from the Bullet library.
*/
-#include "servers/physics_3d/godot_joint_3d.h"
-#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
+#include "../godot_joint_3d.h"
+#include "godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
diff --git a/servers/physics_3d/joints/godot_slider_joint_3d.cpp b/modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp
index b9dca94b37..b9dca94b37 100644
--- a/servers/physics_3d/joints/godot_slider_joint_3d.cpp
+++ b/modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp
diff --git a/servers/physics_3d/joints/godot_slider_joint_3d.h b/modules/godot_physics_3d/joints/godot_slider_joint_3d.h
index ad79fc51b0..99fabf8638 100644
--- a/servers/physics_3d/joints/godot_slider_joint_3d.h
+++ b/modules/godot_physics_3d/joints/godot_slider_joint_3d.h
@@ -35,8 +35,8 @@
Adapted to Godot from the Bullet library.
*/
-#include "servers/physics_3d/godot_joint_3d.h"
-#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
+#include "../godot_joint_3d.h"
+#include "godot_jacobian_entry_3d.h"
/*
Bullet Continuous Collision Detection and Physics Library
diff --git a/modules/godot_physics_3d/register_types.cpp b/modules/godot_physics_3d/register_types.cpp
new file mode 100644
index 0000000000..1b1690cf59
--- /dev/null
+++ b/modules/godot_physics_3d/register_types.cpp
@@ -0,0 +1,61 @@
+/**************************************************************************/
+/* register_types.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "register_types.h"
+
+#include "godot_physics_server_3d.h"
+#include "servers/physics_server_3d.h"
+#include "servers/physics_server_3d_wrap_mt.h"
+
+static PhysicsServer3D *_createGodotPhysics3DCallback() {
+#ifdef THREADS_ENABLED
+ bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread");
+#else
+ bool using_threads = false;
+#endif
+
+ PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads));
+
+ return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads));
+}
+
+void initialize_godot_physics_3d_module(ModuleInitializationLevel p_level) {
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) {
+ return;
+ }
+ PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback));
+ PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
+}
+
+void uninitialize_godot_physics_3d_module(ModuleInitializationLevel p_level) {
+ if (p_level != MODULE_INITIALIZATION_LEVEL_SERVERS) {
+ return;
+ }
+}
diff --git a/modules/godot_physics_3d/register_types.h b/modules/godot_physics_3d/register_types.h
new file mode 100644
index 0000000000..998fb4a1ee
--- /dev/null
+++ b/modules/godot_physics_3d/register_types.h
@@ -0,0 +1,39 @@
+/**************************************************************************/
+/* register_types.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef GODOT_PHYSICS_3D_REGISTER_TYPES_H
+#define GODOT_PHYSICS_3D_REGISTER_TYPES_H
+
+#include "modules/register_module_types.h"
+
+void initialize_godot_physics_3d_module(ModuleInitializationLevel p_level);
+void uninitialize_godot_physics_3d_module(ModuleInitializationLevel p_level);
+
+#endif // GODOT_PHYSICS_3D_REGISTER_TYPES_H
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index e84b4e92c7..788b46ab9a 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
+using System.Reflection;
using GodotTools.Build;
using GodotTools.Ides;
using GodotTools.Ides.Rider;
@@ -701,6 +702,23 @@ namespace GodotTools
private static IntPtr InternalCreateInstance(IntPtr unmanagedCallbacks, int unmanagedCallbacksSize)
{
Internal.Initialize(unmanagedCallbacks, unmanagedCallbacksSize);
+
+ var populateConstructorMethod =
+ AppDomain.CurrentDomain
+ .GetAssemblies()
+ .First(x => x.GetName().Name == "GodotSharpEditor")
+ .GetType("Godot.EditorConstructors")?
+ .GetMethod("AddEditorConstructors",
+ BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
+
+ if (populateConstructorMethod == null)
+ {
+ throw new MissingMethodException("Godot.EditorConstructors",
+ "AddEditorConstructors");
+ }
+
+ populateConstructorMethod.Invoke(null, null);
+
return new GodotSharpEditor().NativeInstance;
}
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index d0adf39fb2..a467aae2e9 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -77,6 +77,10 @@ StringBuilder &operator<<(StringBuilder &r_sb, const char *p_cstring) {
#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
#define BINDINGS_NATIVE_NAME_FIELD "NativeName"
+#define BINDINGS_CLASS_CONSTRUCTOR "Constructors"
+#define BINDINGS_CLASS_CONSTRUCTOR_EDITOR "EditorConstructors"
+#define BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY "BuiltInMethodConstructors"
+
#define CS_PARAM_MEMORYOWN "memoryOwn"
#define CS_PARAM_METHODBIND "method"
#define CS_PARAM_INSTANCE "ptr"
@@ -1737,6 +1741,69 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
compile_items.push_back(output_file);
}
+ // Generate source file for built-in type constructor dictionary.
+
+ {
+ StringBuilder cs_built_in_ctors_content;
+
+ cs_built_in_ctors_content.append("namespace " BINDINGS_NAMESPACE ";\n\n");
+ cs_built_in_ctors_content.append("using System;\n"
+ "using System.Collections.Generic;\n"
+ "\n");
+ cs_built_in_ctors_content.append("internal static class " BINDINGS_CLASS_CONSTRUCTOR "\n{");
+
+ cs_built_in_ctors_content.append(MEMBER_BEGIN "internal static readonly Dictionary<string, Func<IntPtr, GodotObject>> " BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY ";\n");
+
+ cs_built_in_ctors_content.append(MEMBER_BEGIN "public static GodotObject Invoke(string nativeTypeNameStr, IntPtr nativeObjectPtr)\n");
+ cs_built_in_ctors_content.append(INDENT1 OPEN_BLOCK);
+ cs_built_in_ctors_content.append(INDENT2 "if (!" BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY ".TryGetValue(nativeTypeNameStr, out var constructor))\n");
+ cs_built_in_ctors_content.append(INDENT3 "throw new InvalidOperationException(\"Wrapper class not found for type: \" + nativeTypeNameStr);\n");
+ cs_built_in_ctors_content.append(INDENT2 "return constructor(nativeObjectPtr);\n");
+ cs_built_in_ctors_content.append(INDENT1 CLOSE_BLOCK);
+
+ cs_built_in_ctors_content.append(MEMBER_BEGIN "static " BINDINGS_CLASS_CONSTRUCTOR "()\n");
+ cs_built_in_ctors_content.append(INDENT1 OPEN_BLOCK);
+ cs_built_in_ctors_content.append(INDENT2 BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY " = new();\n");
+
+ for (const KeyValue<StringName, TypeInterface> &E : obj_types) {
+ const TypeInterface &itype = E.value;
+
+ if (itype.api_type != ClassDB::API_CORE || itype.is_singleton_instance) {
+ continue;
+ }
+
+ if (itype.is_deprecated) {
+ cs_built_in_ctors_content.append("#pragma warning disable CS0618\n");
+ }
+
+ cs_built_in_ctors_content.append(INDENT2 BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY ".Add(\"");
+ cs_built_in_ctors_content.append(itype.name);
+ cs_built_in_ctors_content.append("\", " CS_PARAM_INSTANCE " => new ");
+ cs_built_in_ctors_content.append(itype.proxy_name);
+ if (itype.is_singleton && !itype.is_compat_singleton) {
+ cs_built_in_ctors_content.append("Instance");
+ }
+ cs_built_in_ctors_content.append("(" CS_PARAM_INSTANCE "));\n");
+
+ if (itype.is_deprecated) {
+ cs_built_in_ctors_content.append("#pragma warning restore CS0618\n");
+ }
+ }
+
+ cs_built_in_ctors_content.append(INDENT1 CLOSE_BLOCK);
+
+ cs_built_in_ctors_content.append(CLOSE_BLOCK);
+
+ String constructors_file = path::join(base_gen_dir, BINDINGS_CLASS_CONSTRUCTOR ".cs");
+ Error err = _save_file(constructors_file, cs_built_in_ctors_content);
+
+ if (err != OK) {
+ return err;
+ }
+
+ compile_items.push_back(constructors_file);
+ }
+
// Generate native calls
StringBuilder cs_icalls_content;
@@ -1844,6 +1911,57 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
compile_items.push_back(output_file);
}
+ // Generate source file for editor type constructor dictionary.
+
+ {
+ StringBuilder cs_built_in_ctors_content;
+
+ cs_built_in_ctors_content.append("namespace " BINDINGS_NAMESPACE ";\n\n");
+ cs_built_in_ctors_content.append("internal static class " BINDINGS_CLASS_CONSTRUCTOR_EDITOR "\n{");
+
+ cs_built_in_ctors_content.append(MEMBER_BEGIN "private static void AddEditorConstructors()\n");
+ cs_built_in_ctors_content.append(INDENT1 OPEN_BLOCK);
+ cs_built_in_ctors_content.append(INDENT2 "var builtInMethodConstructors = " BINDINGS_CLASS_CONSTRUCTOR "." BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY ";\n");
+
+ for (const KeyValue<StringName, TypeInterface> &E : obj_types) {
+ const TypeInterface &itype = E.value;
+
+ if (itype.api_type != ClassDB::API_EDITOR || itype.is_singleton_instance) {
+ continue;
+ }
+
+ if (itype.is_deprecated) {
+ cs_built_in_ctors_content.append("#pragma warning disable CS0618\n");
+ }
+
+ cs_built_in_ctors_content.append(INDENT2 "builtInMethodConstructors.Add(\"");
+ cs_built_in_ctors_content.append(itype.name);
+ cs_built_in_ctors_content.append("\", " CS_PARAM_INSTANCE " => new ");
+ cs_built_in_ctors_content.append(itype.proxy_name);
+ if (itype.is_singleton && !itype.is_compat_singleton) {
+ cs_built_in_ctors_content.append("Instance");
+ }
+ cs_built_in_ctors_content.append("(" CS_PARAM_INSTANCE "));\n");
+
+ if (itype.is_deprecated) {
+ cs_built_in_ctors_content.append("#pragma warning restore CS0618\n");
+ }
+ }
+
+ cs_built_in_ctors_content.append(INDENT1 CLOSE_BLOCK);
+
+ cs_built_in_ctors_content.append(CLOSE_BLOCK);
+
+ String constructors_file = path::join(base_gen_dir, BINDINGS_CLASS_CONSTRUCTOR_EDITOR ".cs");
+ Error err = _save_file(constructors_file, cs_built_in_ctors_content);
+
+ if (err != OK) {
+ return err;
+ }
+
+ compile_items.push_back(constructors_file);
+ }
+
// Generate native calls
StringBuilder cs_icalls_content;
@@ -2210,6 +2328,15 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
<< CLOSE_BLOCK_L2 CLOSE_BLOCK_L1;
}
+ output << MEMBER_BEGIN "internal " << itype.proxy_name << "(IntPtr " CS_PARAM_INSTANCE ") : this("
+ << (itype.memory_own ? "true" : "false") << ")\n" OPEN_BLOCK_L1
+ << INDENT2 "NativePtr = " CS_PARAM_INSTANCE ";\n"
+ << INDENT2 "unsafe\n" INDENT2 OPEN_BLOCK
+ << INDENT3 "ConstructAndInitialize(null, "
+ << BINDINGS_NATIVE_NAME_FIELD ", CachedType, refCounted: "
+ << (itype.is_ref_counted ? "true" : "false") << ");\n"
+ << CLOSE_BLOCK_L2 CLOSE_BLOCK_L1;
+
// Add.. em.. trick constructor. Sort of.
output.append(MEMBER_BEGIN "internal ");
output.append(itype.proxy_name);
@@ -2934,11 +3061,6 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output) {
String arguments_sig;
- String delegate_type_params;
-
- if (!p_isignal.arguments.is_empty()) {
- delegate_type_params += "<";
- }
// Retrieve information from the arguments
const ArgumentInterface &first = p_isignal.arguments.front()->get();
@@ -2959,18 +3081,13 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
if (&iarg != &first) {
arguments_sig += ", ";
- delegate_type_params += ", ";
}
- arguments_sig += arg_type->cs_type;
+ String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
+
+ arguments_sig += arg_cs_type;
arguments_sig += " ";
arguments_sig += iarg.name;
-
- delegate_type_params += arg_type->cs_type;
- }
-
- if (!p_isignal.arguments.is_empty()) {
- delegate_type_params += ">";
}
// Generate signal
@@ -3019,8 +3136,14 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
p_output << ", ";
}
- p_output << sformat(arg_type->cs_variant_to_managed,
- "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name);
+ if (arg_type->cname == name_cache.type_Array_generic || arg_type->cname == name_cache.type_Dictionary_generic) {
+ String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters);
+
+ p_output << "new " << arg_cs_type << "(" << sformat(arg_type->cs_variant_to_managed, "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name) << ")";
+ } else {
+ p_output << sformat(arg_type->cs_variant_to_managed,
+ "args[" + itos(idx) + "]", arg_type->cs_type, arg_type->name);
+ }
idx++;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
index 901700067d..1b3062c5db 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs
@@ -93,27 +93,15 @@ namespace Godot.Bridge
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
IntPtr godotObject)
{
- // TODO: Optimize with source generators and delegate pointers.
-
try
{
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName)));
string nativeTypeNameStr = stringName.ToString();
- Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException(
- "Wrapper class not found for type: " + nativeTypeNameStr);
- var obj = (GodotObject)FormatterServices.GetUninitializedObject(nativeType);
-
- var ctor = nativeType.GetConstructor(
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
- null, Type.EmptyTypes, null);
-
- obj.NativePtr = godotObject;
-
- _ = ctor!.Invoke(obj, null);
+ var instance = Constructors.Invoke(nativeTypeNameStr, godotObject);
- return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(obj));
+ return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance));
}
catch (Exception e)
{
@@ -308,66 +296,6 @@ namespace Godot.Bridge
}
}
- private static Type? TypeGetProxyClass(string nativeTypeNameStr)
- {
- // Performance is not critical here as this will be replaced with a generated dictionary.
-
- if (nativeTypeNameStr[0] == '_')
- nativeTypeNameStr = nativeTypeNameStr.Substring(1);
-
- Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr);
-
- if (wrapperType == null)
- {
- wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr);
- }
-
- if (wrapperType == null)
- {
- var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
- .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
-
- if (editorAssembly != null)
- {
- wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr);
-
- if (wrapperType == null)
- {
- wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
- }
- }
- }
-
- static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr)
- {
- var types = assembly.GetTypes();
- foreach (var type in types)
- {
- var attr = type.GetCustomAttribute<GodotClassNameAttribute>();
- if (attr?.Name == nativeTypeNameStr)
- {
- return type;
- }
- }
- return null;
- }
-
- static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
-
- if (wrapperType != null && IsStatic(wrapperType))
- {
- // A static class means this is a Godot singleton class. Try to get the Instance proxy type.
- wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance");
- if (wrapperType == null)
- {
- // Otherwise, fallback to GodotObject.
- return typeof(GodotObject);
- }
- }
-
- return wrapperType;
- }
-
// Called from GodotPlugins
// ReSharper disable once UnusedMember.Local
public static void LookupScriptsInAssembly(Assembly assembly)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
index c094eaed77..a429931399 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs
@@ -29,6 +29,17 @@ namespace Godot
}
}
+ internal GodotObject(IntPtr nativePtr) : this(false)
+ {
+ // NativePtr must be non-zero before calling ConstructAndInitialize to avoid invoking the constructor NativeCtor.
+ // We don't want to invoke the constructor, because we already have a constructed instance in nativePtr.
+ NativePtr = nativePtr;
+ unsafe
+ {
+ ConstructAndInitialize(NativeCtor, NativeName, _cachedType, refCounted: false);
+ }
+ }
+
internal unsafe void ConstructAndInitialize(
delegate* unmanaged<godot_bool, IntPtr> nativeCtor,
StringName nativeName,
diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
index 338d632524..813c9d582e 100644
--- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
+++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
@@ -178,6 +178,15 @@
[param layer] is a pointer to an [code]XrCompositionLayerBaseHeader[/code] struct.
</description>
</method>
+ <method name="_set_android_surface_swapchain_create_info_and_get_next_pointer" qualifiers="virtual">
+ <return type="int" />
+ <param index="0" name="property_values" type="Dictionary" />
+ <param index="1" name="next_pointer" type="void*" />
+ <description>
+ Adds additional data structures to Android surface swapchains created by [OpenXRCompositionLayer].
+ [param property_values] contains the values of the properties returned by [method _get_viewport_composition_layer_extension_properties].
+ </description>
+ </method>
<method name="_set_hand_joint_locations_and_get_next_pointer" qualifiers="virtual">
<return type="int" />
<param index="0" name="hand_index" type="int" />
diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
index 83e45ffe7f..dc30b95b27 100644
--- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp
+++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
@@ -144,7 +144,6 @@ bool OpenXRCompositionLayerExtension::create_android_surface_swapchain(XrSwapcha
OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
ERR_FAIL_NULL_V(openxr_api, false);
- // @todo We need a way to add to the next pointer chain.
XrResult result = xrCreateSwapchainAndroidSurfaceKHR(openxr_api->get_session(), p_info, r_swapchain, r_surface);
if (XR_FAILED(result)) {
print_line("OpenXR: Failed to create Android surface swapchain [", openxr_api->get_error_string(result), "]");
@@ -254,11 +253,19 @@ void OpenXRViewportCompositionLayerProvider::create_android_surface() {
ERR_FAIL_COND(android_surface.swapchain != XR_NULL_HANDLE || android_surface.surface.is_valid());
ERR_FAIL_COND(!openxr_api || !openxr_api->is_running());
+ void *next_pointer = nullptr;
+ for (OpenXRExtensionWrapper *wrapper : openxr_api->get_registered_extension_wrappers()) {
+ void *np = wrapper->set_android_surface_swapchain_create_info_and_get_next_pointer(extension_property_values, next_pointer);
+ if (np != nullptr) {
+ next_pointer = np;
+ }
+ }
+
// The XR_FB_android_surface_swapchain_create extension mandates that format, sampleCount,
// faceCount, arraySize, and mipCount must be zero.
XrSwapchainCreateInfo info = {
XR_TYPE_SWAPCHAIN_CREATE_INFO, // type
- nullptr, // next
+ next_pointer, // next
0, // createFlags
XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, // usageFlags
0, // format
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 09a9556dfa..95b537d1b4 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -97,10 +97,11 @@ public:
virtual void on_state_loss_pending() {} // `on_state_loss_pending` is called when the OpenXR session state is changed to loss pending.
virtual void on_state_exiting() {} // `on_state_exiting` is called when the OpenXR session state is changed to exiting.
- virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) { return p_next_pointer; } // Add additional data structures to composition layers created via OpenXRCompositionLayer.
+ virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, const Dictionary &p_property_values, void *p_next_pointer) { return p_next_pointer; } // Add additional data structures to composition layers created via OpenXRCompositionLayer.
virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) {} // `on_viewport_composition_layer_destroyed` is called when a composition layer created via OpenXRCompositionLayer is destroyed.
virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) {} // Get additional property definitions for OpenXRCompositionLayer.
virtual Dictionary get_viewport_composition_layer_extension_property_defaults() { return Dictionary(); } // Get the default values for the additional property definitions for OpenXRCompositionLayer.
+ virtual void *set_android_surface_swapchain_create_info_and_get_next_pointer(const Dictionary &p_property_values, void *p_next_pointer) { return p_next_pointer; }
// `on_event_polled` is called when there is an OpenXR event to process.
// Should return true if the event was handled, false otherwise.
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
index e09ca484d5..07ca476421 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
@@ -65,6 +65,7 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_properties);
GDVIRTUAL_BIND(_get_viewport_composition_layer_extension_property_defaults);
GDVIRTUAL_BIND(_on_viewport_composition_layer_destroyed, "layer");
+ GDVIRTUAL_BIND(_set_android_surface_swapchain_create_info_and_get_next_pointer, "property_values", "next_pointer");
ClassDB::bind_method(D_METHOD("get_openxr_api"), &OpenXRExtensionWrapperExtension::get_openxr_api);
ClassDB::bind_method(D_METHOD("register_extension_wrapper"), &OpenXRExtensionWrapperExtension::register_extension_wrapper);
@@ -249,7 +250,7 @@ bool OpenXRExtensionWrapperExtension::on_event_polled(const XrEventDataBuffer &p
return false;
}
-void *OpenXRExtensionWrapperExtension::set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) {
+void *OpenXRExtensionWrapperExtension::set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, const Dictionary &p_property_values, void *p_next_pointer) {
uint64_t pointer = 0;
if (GDVIRTUAL_CALL(_set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>(p_layer), p_property_values, GDExtensionPtr<void>(p_next_pointer), pointer)) {
@@ -279,6 +280,16 @@ Dictionary OpenXRExtensionWrapperExtension::get_viewport_composition_layer_exten
return property_defaults;
}
+void *OpenXRExtensionWrapperExtension::set_android_surface_swapchain_create_info_and_get_next_pointer(const Dictionary &p_property_values, void *p_next_pointer) {
+ uint64_t pointer = 0;
+
+ if (GDVIRTUAL_CALL(_set_android_surface_swapchain_create_info_and_get_next_pointer, p_property_values, GDExtensionPtr<void>(p_next_pointer), pointer)) {
+ return reinterpret_cast<void *>(pointer);
+ }
+
+ return p_next_pointer;
+}
+
Ref<OpenXRAPIExtension> OpenXRExtensionWrapperExtension::get_openxr_api() {
return openxr_api;
}
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
index e37853903b..5cdf288c93 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
@@ -121,15 +121,17 @@ public:
GDVIRTUAL1R(bool, _on_event_polled, GDExtensionConstPtr<void>);
- virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, Dictionary p_property_values, void *p_next_pointer) override;
+ virtual void *set_viewport_composition_layer_and_get_next_pointer(const XrCompositionLayerBaseHeader *p_layer, const Dictionary &p_property_values, void *p_next_pointer) override;
virtual void on_viewport_composition_layer_destroyed(const XrCompositionLayerBaseHeader *p_layer) override;
virtual void get_viewport_composition_layer_extension_properties(List<PropertyInfo> *p_property_list) override;
virtual Dictionary get_viewport_composition_layer_extension_property_defaults() override;
+ virtual void *set_android_surface_swapchain_create_info_and_get_next_pointer(const Dictionary &p_property_values, void *p_next_pointer) override;
GDVIRTUAL3R(uint64_t, _set_viewport_composition_layer_and_get_next_pointer, GDExtensionConstPtr<void>, Dictionary, GDExtensionPtr<void>);
GDVIRTUAL1(_on_viewport_composition_layer_destroyed, GDExtensionConstPtr<void>);
GDVIRTUAL0R(TypedArray<Dictionary>, _get_viewport_composition_layer_extension_properties);
GDVIRTUAL0R(Dictionary, _get_viewport_composition_layer_extension_property_defaults);
+ GDVIRTUAL2R(uint64_t, _set_android_surface_swapchain_create_info_and_get_next_pointer, Dictionary, GDExtensionPtr<void>);
Ref<OpenXRAPIExtension> get_openxr_api();
diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp
index 6bdb261b50..4305bf842a 100644
--- a/modules/upnp/upnp.cpp
+++ b/modules/upnp/upnp.cpp
@@ -131,7 +131,11 @@ void UPNP::parse_igd(Ref<UPNPDevice> dev, UPNPDev *devlist) {
GetUPNPUrls(&urls, &data, dev->get_description_url().utf8().get_data(), 0);
char addr[16];
+#if MINIUPNPC_API_VERSION >= 18
+ int i = UPNP_GetValidIGD(devlist, &urls, &data, (char *)&addr, 16, nullptr, 0);
+#else
int i = UPNP_GetValidIGD(devlist, &urls, &data, (char *)&addr, 16);
+#endif
if (i != 1) {
FreeUPNPUrls(&urls);
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index db4c743595..9adab7284c 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -620,18 +620,16 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
sys.exit(255)
- env.Append(CCFLAGS=["-flto=thin"])
- env.Append(LINKFLAGS=["-flto=thin"])
+ env.AppendUnique(CCFLAGS=["-flto=thin"])
elif env["use_llvm"]:
- env.Append(CCFLAGS=["-flto"])
- env.Append(LINKFLAGS=["-flto"])
+ env.AppendUnique(CCFLAGS=["-flto"])
else:
env.AppendUnique(CCFLAGS=["/GL"])
- env.AppendUnique(ARFLAGS=["/LTCG"])
- if env["progress"]:
- env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
- else:
- env.AppendUnique(LINKFLAGS=["/LTCG"])
+ if env["progress"]:
+ env.AppendUnique(LINKFLAGS=["/LTCG:STATUS"])
+ else:
+ env.AppendUnique(LINKFLAGS=["/LTCG"])
+ env.AppendUnique(ARFLAGS=["/LTCG"])
if vcvars_msvc_config:
env.Prepend(CPPPATH=[p for p in str(os.getenv("INCLUDE")).split(";")])
diff --git a/scene/3d/physics/character_body_3d.cpp b/scene/3d/physics/character_body_3d.cpp
index dda3ea9cca..e3815e8219 100644
--- a/scene/3d/physics/character_body_3d.cpp
+++ b/scene/3d/physics/character_body_3d.cpp
@@ -60,8 +60,13 @@ bool CharacterBody3D::move_and_slide() {
// We need to check the platform_rid object still exists before accessing.
// A valid RID is no guarantee that the object has not been deleted.
- if (ObjectDB::get_instance(platform_object_id)) {
- //this approach makes sure there is less delay between the actual body velocity and the one we saved
+
+ // We can only perform the ObjectDB lifetime check on Object derived objects.
+ // Note that physics also creates RIDs for non-Object derived objects, these cannot
+ // be lifetime checked through ObjectDB, and therefore there is a still a vulnerability
+ // to dangling RIDs (access after free) in this scenario.
+ if (platform_object_id.is_null() || ObjectDB::get_instance(platform_object_id)) {
+ // This approach makes sure there is less delay between the actual body velocity and the one we saved.
bs = PhysicsServer3D::get_singleton()->body_get_direct_state(platform_rid);
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index c3287035ff..635228670d 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -831,6 +831,9 @@ void CodeEdit::_cut_internal(int p_caret) {
delete_selection(p_caret);
return;
}
+ if (!is_empty_selection_clipboard_enabled()) {
+ return;
+ }
if (p_caret == -1) {
delete_lines();
} else {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 687ca4d4d4..0e8d76d294 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -3367,6 +3367,14 @@ bool TextEdit::is_middle_mouse_paste_enabled() const {
return middle_mouse_paste_enabled;
}
+void TextEdit::set_empty_selection_clipboard_enabled(bool p_enabled) {
+ empty_selection_clipboard_enabled = p_enabled;
+}
+
+bool TextEdit::is_empty_selection_clipboard_enabled() const {
+ return empty_selection_clipboard_enabled;
+}
+
// Text manipulation
void TextEdit::clear() {
setting_text = true;
@@ -6569,6 +6577,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enabled"), &TextEdit::set_middle_mouse_paste_enabled);
ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &TextEdit::is_middle_mouse_paste_enabled);
+ ClassDB::bind_method(D_METHOD("set_empty_selection_clipboard_enabled", "enabled"), &TextEdit::set_empty_selection_clipboard_enabled);
+ ClassDB::bind_method(D_METHOD("is_empty_selection_clipboard_enabled"), &TextEdit::is_empty_selection_clipboard_enabled);
+
// Text manipulation
ClassDB::bind_method(D_METHOD("clear"), &TextEdit::clear);
@@ -6962,6 +6973,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_and_drop_selection_enabled"), "set_drag_and_drop_selection_enabled", "is_drag_and_drop_selection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "empty_selection_clipboard_enabled"), "set_empty_selection_clipboard_enabled", "is_empty_selection_clipboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Arbitrary:1,Word:2,Word (Smart):3"), "set_autowrap_mode", "get_autowrap_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_wrapped_lines"), "set_indent_wrapped_lines", "is_indent_wrapped_lines");
@@ -7216,6 +7228,10 @@ void TextEdit::_cut_internal(int p_caret) {
return;
}
+ if (!empty_selection_clipboard_enabled) {
+ return;
+ }
+
// Remove full lines.
begin_complex_operation();
begin_multicaret_edit();
@@ -7246,6 +7262,10 @@ void TextEdit::_copy_internal(int p_caret) {
return;
}
+ if (!empty_selection_clipboard_enabled) {
+ return;
+ }
+
// Copy full lines.
StringBuilder clipboard;
Vector<Point2i> line_ranges;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index c5f838020b..94b105d486 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -319,6 +319,7 @@ private:
bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
bool middle_mouse_paste_enabled = true;
+ bool empty_selection_clipboard_enabled = true;
// Overridable actions.
String cut_copy_line = "";
@@ -770,6 +771,9 @@ public:
void set_middle_mouse_paste_enabled(bool p_enabled);
bool is_middle_mouse_paste_enabled() const;
+ void set_empty_selection_clipboard_enabled(bool p_enabled);
+ bool is_empty_selection_clipboard_enabled() const;
+
// Text manipulation
void clear();
diff --git a/scene/resources/external_texture.cpp b/scene/resources/external_texture.cpp
index c088406030..0552bbd081 100644
--- a/scene/resources/external_texture.cpp
+++ b/scene/resources/external_texture.cpp
@@ -30,9 +30,6 @@
#include "external_texture.h"
-#include "drivers/gles3/storage/texture_storage.h"
-#include "servers/rendering/rendering_server_globals.h"
-
void ExternalTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &ExternalTexture::set_size);
ClassDB::bind_method(D_METHOD("get_external_texture_id"), &ExternalTexture::get_external_texture_id);
diff --git a/scu_builders.py b/scu_builders.py
index fc5461196f..7fc0c15b2d 100644
--- a/scu_builders.py
+++ b/scu_builders.py
@@ -322,6 +322,8 @@ def generate_scu_files(max_includes_per_scu):
process_folder(["modules/openxr"], ["register_types"])
process_folder(["modules/openxr/action_map"])
process_folder(["modules/openxr/editor"])
+ process_folder(["modules/godot_physics_3d"])
+ process_folder(["modules/godot_physics_3d/joints"])
process_folder(["modules/csg"])
process_folder(["modules/gdscript"])
@@ -349,8 +351,6 @@ def generate_scu_files(max_includes_per_scu):
process_folder(["servers/rendering/renderer_rd/environment"])
process_folder(["servers/rendering/renderer_rd/storage_rd"])
process_folder(["servers/physics_2d"])
- process_folder(["servers/physics_3d"])
- process_folder(["servers/physics_3d/joints"])
process_folder(["servers/audio"])
process_folder(["servers/audio/effects"])
diff --git a/servers/SCsub b/servers/SCsub
index 736bed68ec..472cb096ab 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -28,7 +28,6 @@ SConscript("text/SCsub")
SConscript("physics_2d/SCsub")
if not env["disable_3d"]:
- SConscript("physics_3d/SCsub")
env.add_source_files(env.servers_sources, "physics_server_3d.cpp")
env.add_source_files(env.servers_sources, "physics_server_3d_wrap_mt.cpp")
SConscript("xr/SCsub")
diff --git a/servers/physics_3d/SCsub b/servers/physics_3d/SCsub
deleted file mode 100644
index df7b521693..0000000000
--- a/servers/physics_3d/SCsub
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.servers_sources, "*.cpp")
-
-SConscript("joints/SCsub")
diff --git a/servers/physics_3d/joints/SCsub b/servers/physics_3d/joints/SCsub
deleted file mode 100644
index 86681f9c74..0000000000
--- a/servers/physics_3d/joints/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-Import("env")
-
-env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 698805bbdd..ee48151863 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -1201,7 +1201,9 @@ String PhysicsServer3DManager::get_server_name(int p_id) {
}
PhysicsServer3D *PhysicsServer3DManager::new_default_server() {
- ERR_FAIL_COND_V(default_server_id == -1, nullptr);
+ if (default_server_id == -1) {
+ return nullptr;
+ }
Variant ret;
Callable::CallError ce;
physics_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce);
diff --git a/servers/physics_server_3d_dummy.h b/servers/physics_server_3d_dummy.h
new file mode 100644
index 0000000000..209a541fea
--- /dev/null
+++ b/servers/physics_server_3d_dummy.h
@@ -0,0 +1,436 @@
+/**************************************************************************/
+/* physics_server_3d_dummy.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef PHYSICS_SERVER_3D_DUMMY_H
+#define PHYSICS_SERVER_3D_DUMMY_H
+
+#include "servers/physics_server_3d.h"
+
+class PhysicsDirectBodyState3DDummy : public PhysicsDirectBodyState3D {
+ GDCLASS(PhysicsDirectBodyState3DDummy, PhysicsDirectBodyState3D);
+
+ PhysicsDirectSpaceState3D *space_state_dummy = nullptr;
+
+public:
+ virtual Vector3 get_total_gravity() const override { return Vector3(); }
+ virtual real_t get_total_angular_damp() const override { return 0; }
+ virtual real_t get_total_linear_damp() const override { return 0; }
+
+ virtual Vector3 get_center_of_mass() const override { return Vector3(); }
+ virtual Vector3 get_center_of_mass_local() const override { return Vector3(); }
+ virtual Basis get_principal_inertia_axes() const override { return Basis(); }
+ virtual real_t get_inverse_mass() const override { return 0; }
+ virtual Vector3 get_inverse_inertia() const override { return Vector3(); }
+ virtual Basis get_inverse_inertia_tensor() const override { return Basis(); }
+
+ virtual void set_linear_velocity(const Vector3 &p_velocity) override {}
+ virtual Vector3 get_linear_velocity() const override { return Vector3(); }
+
+ virtual void set_angular_velocity(const Vector3 &p_velocity) override {}
+ virtual Vector3 get_angular_velocity() const override { return Vector3(); }
+
+ virtual void set_transform(const Transform3D &p_transform) override {}
+ virtual Transform3D get_transform() const override { return Transform3D(); }
+
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override { return Vector3(); }
+
+ virtual void apply_central_impulse(const Vector3 &p_impulse) override {}
+ virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override {}
+ virtual void apply_torque_impulse(const Vector3 &p_impulse) override {}
+
+ virtual void apply_central_force(const Vector3 &p_force) override {}
+ virtual void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {}
+ virtual void apply_torque(const Vector3 &p_torque) override {}
+
+ virtual void add_constant_central_force(const Vector3 &p_force) override {}
+ virtual void add_constant_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {}
+ virtual void add_constant_torque(const Vector3 &p_torque) override {}
+
+ virtual void set_constant_force(const Vector3 &p_force) override {}
+ virtual Vector3 get_constant_force() const override { return Vector3(); }
+
+ virtual void set_constant_torque(const Vector3 &p_torque) override {}
+ virtual Vector3 get_constant_torque() const override { return Vector3(); }
+
+ virtual void set_sleep_state(bool p_sleep) override {}
+ virtual bool is_sleeping() const override { return false; }
+
+ virtual int get_contact_count() const override { return 0; }
+
+ virtual Vector3 get_contact_local_position(int p_contact_idx) const override { return Vector3(); }
+ virtual Vector3 get_contact_local_normal(int p_contact_idx) const override { return Vector3(); }
+ virtual Vector3 get_contact_impulse(int p_contact_idx) const override { return Vector3(); }
+ virtual int get_contact_local_shape(int p_contact_idx) const override { return 0; }
+ virtual Vector3 get_contact_local_velocity_at_position(int p_contact_idx) const override { return Vector3(); }
+
+ virtual RID get_contact_collider(int p_contact_idx) const override { return RID(); }
+ virtual Vector3 get_contact_collider_position(int p_contact_idx) const override { return Vector3(); }
+ virtual ObjectID get_contact_collider_id(int p_contact_idx) const override { return ObjectID(); }
+ virtual Object *get_contact_collider_object(int p_contact_idx) const override { return nullptr; }
+ virtual int get_contact_collider_shape(int p_contact_idx) const override { return 0; }
+ virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const override { return Vector3(); }
+
+ virtual real_t get_step() const override { return 0; }
+ virtual void integrate_forces() override {}
+
+ virtual PhysicsDirectSpaceState3D *get_space_state() override { return space_state_dummy; }
+
+ PhysicsDirectBodyState3DDummy(PhysicsDirectSpaceState3D *p_space_state_dummy) {
+ space_state_dummy = p_space_state_dummy;
+ }
+};
+
+class PhysicsDirectSpaceState3DDummy : public PhysicsDirectSpaceState3D {
+ GDCLASS(PhysicsDirectSpaceState3DDummy, PhysicsDirectSpaceState3D);
+
+public:
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override { return false; }
+
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { return 0; }
+
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { return 0; }
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe, ShapeRestInfo *r_info = nullptr) override { return false; }
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector3 *r_results, int p_result_max, int &r_result_count) override { return false; }
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override { return false; }
+
+ virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override { return Vector3(); }
+};
+
+class PhysicsServer3DDummy : public PhysicsServer3D {
+ GDCLASS(PhysicsServer3DDummy, PhysicsServer3D);
+
+ PhysicsDirectBodyState3DDummy *body_state_dummy = nullptr;
+ PhysicsDirectSpaceState3DDummy *space_state_dummy = nullptr;
+
+public:
+ virtual RID world_boundary_shape_create() override { return RID(); }
+ virtual RID separation_ray_shape_create() override { return RID(); }
+ virtual RID sphere_shape_create() override { return RID(); }
+ virtual RID box_shape_create() override { return RID(); }
+ virtual RID capsule_shape_create() override { return RID(); }
+ virtual RID cylinder_shape_create() override { return RID(); }
+ virtual RID convex_polygon_shape_create() override { return RID(); }
+ virtual RID concave_polygon_shape_create() override { return RID(); }
+ virtual RID heightmap_shape_create() override { return RID(); }
+ virtual RID custom_shape_create() override { return RID(); }
+
+ virtual void shape_set_data(RID p_shape, const Variant &p_data) override {}
+ virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) override {}
+
+ virtual ShapeType shape_get_type(RID p_shape) const override { return SHAPE_SPHERE; }
+ virtual Variant shape_get_data(RID p_shape) const override { return Variant(); }
+
+ virtual void shape_set_margin(RID p_shape, real_t p_margin) override {}
+ virtual real_t shape_get_margin(RID p_shape) const override { return 0; }
+
+ virtual real_t shape_get_custom_solver_bias(RID p_shape) const override { return 0; }
+
+ /* SPACE API */
+
+ virtual RID space_create() override { return RID(); }
+ virtual void space_set_active(RID p_space, bool p_active) override {}
+ virtual bool space_is_active(RID p_space) const override { return false; }
+
+ virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) override {}
+ virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const override { return 0; }
+
+ virtual PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) override { return space_state_dummy; }
+
+ virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) override {}
+ virtual Vector<Vector3> space_get_contacts(RID p_space) const override { return Vector<Vector3>(); }
+ virtual int space_get_contact_count(RID p_space) const override { return 0; }
+
+ /* AREA API */
+
+ virtual RID area_create() override { return RID(); }
+
+ virtual void area_set_space(RID p_area, RID p_space) override {}
+ virtual RID area_get_space(RID p_area) const override { return RID(); }
+
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override {}
+ virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) override {}
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) override {}
+
+ virtual int area_get_shape_count(RID p_area) const override { return 0; }
+ virtual RID area_get_shape(RID p_area, int p_shape_idx) const override { return RID(); }
+ virtual Transform3D area_get_shape_transform(RID p_area, int p_shape_idx) const override { return Transform3D(); }
+
+ virtual void area_remove_shape(RID p_area, int p_shape_idx) override {}
+ virtual void area_clear_shapes(RID p_area) override {}
+
+ virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) override {}
+
+ virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) override {}
+ virtual ObjectID area_get_object_instance_id(RID p_area) const override { return ObjectID(); }
+
+ virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) override {}
+ virtual void area_set_transform(RID p_area, const Transform3D &p_transform) override {}
+
+ virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const override { return Variant(); }
+ virtual Transform3D area_get_transform(RID p_area) const override { return Transform3D(); }
+
+ virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override {}
+ virtual uint32_t area_get_collision_layer(RID p_area) const override { return 0; }
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override {}
+ virtual uint32_t area_get_collision_mask(RID p_area) const override { return 0; }
+
+ virtual void area_set_monitorable(RID p_area, bool p_monitorable) override {}
+
+ virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override {}
+ virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override {}
+
+ virtual void area_set_ray_pickable(RID p_area, bool p_enable) override {}
+
+ /* BODY API */
+
+ virtual RID body_create() override { return RID(); }
+
+ virtual void body_set_space(RID p_body, RID p_space) override {}
+ virtual RID body_get_space(RID p_body) const override { return RID(); }
+
+ virtual void body_set_mode(RID p_body, BodyMode p_mode) override {}
+ virtual BodyMode body_get_mode(RID p_body) const override { return BodyMode::BODY_MODE_STATIC; }
+
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false) override {}
+ virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) override {}
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) override {}
+
+ virtual int body_get_shape_count(RID p_body) const override { return 0; }
+ virtual RID body_get_shape(RID p_body, int p_shape_idx) const override { return RID(); }
+ virtual Transform3D body_get_shape_transform(RID p_body, int p_shape_idx) const override { return Transform3D(); }
+
+ virtual void body_remove_shape(RID p_body, int p_shape_idx) override {}
+ virtual void body_clear_shapes(RID p_body) override {}
+
+ virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) override {}
+
+ virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) override {}
+ virtual ObjectID body_get_object_instance_id(RID p_body) const override { return ObjectID(); }
+
+ virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) override {}
+ virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const override { return false; }
+
+ virtual void body_set_collision_layer(RID p_body, uint32_t p_layer) override {}
+ virtual uint32_t body_get_collision_layer(RID p_body) const override { return 0; }
+
+ virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override {}
+ virtual uint32_t body_get_collision_mask(RID p_body) const override { return 0; }
+
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) override {}
+ virtual real_t body_get_collision_priority(RID p_body) const override { return 0; }
+
+ virtual void body_set_user_flags(RID p_body, uint32_t p_flags) override {}
+ virtual uint32_t body_get_user_flags(RID p_body) const override { return 0; }
+
+ virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override {}
+ virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override { return Variant(); }
+
+ virtual void body_reset_mass_properties(RID p_body) override {}
+
+ virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override {}
+ virtual Variant body_get_state(RID p_body, BodyState p_state) const override { return Variant(); }
+
+ virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) override {}
+ virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) override {}
+ virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) override {}
+
+ virtual void body_apply_central_force(RID p_body, const Vector3 &p_force) override {}
+ virtual void body_apply_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {}
+ virtual void body_apply_torque(RID p_body, const Vector3 &p_torque) override {}
+
+ virtual void body_add_constant_central_force(RID p_body, const Vector3 &p_force) override {}
+ virtual void body_add_constant_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {}
+ virtual void body_add_constant_torque(RID p_body, const Vector3 &p_torque) override {}
+
+ virtual void body_set_constant_force(RID p_body, const Vector3 &p_force) override {}
+ virtual Vector3 body_get_constant_force(RID p_body) const override { return Vector3(); }
+
+ virtual void body_set_constant_torque(RID p_body, const Vector3 &p_torque) override {}
+ virtual Vector3 body_get_constant_torque(RID p_body) const override { return Vector3(); }
+
+ virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) override {}
+
+ virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) override {}
+ virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const override { return false; }
+
+ virtual void body_add_collision_exception(RID p_body, RID p_body_b) override {}
+ virtual void body_remove_collision_exception(RID p_body, RID p_body_b) override {}
+ virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {}
+
+ virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override {}
+ virtual int body_get_max_contacts_reported(RID p_body) const override { return 0; }
+
+ virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) override {}
+ virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const override { return 0; }
+
+ virtual void body_set_omit_force_integration(RID p_body, bool p_omit) override {}
+ virtual bool body_is_omitting_force_integration(RID p_body) const override { return false; }
+
+ virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) override {}
+ virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override {}
+
+ virtual void body_set_ray_pickable(RID p_body, bool p_enable) override {}
+
+ virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override { return body_state_dummy; }
+
+ virtual bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { return false; }
+
+ /* SOFT BODY */
+
+ virtual RID soft_body_create() override { return RID(); }
+
+ virtual void soft_body_update_rendering_server(RID p_body, PhysicsServer3DRenderingServerHandler *p_rendering_server_handler) override {}
+
+ virtual void soft_body_set_space(RID p_body, RID p_space) override {}
+ virtual RID soft_body_get_space(RID p_body) const override { return RID(); }
+
+ virtual void soft_body_set_mesh(RID p_body, RID p_mesh) override {}
+
+ virtual AABB soft_body_get_bounds(RID p_body) const override { return AABB(); }
+
+ virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) override {}
+ virtual uint32_t soft_body_get_collision_layer(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) override {}
+ virtual uint32_t soft_body_get_collision_mask(RID p_body) const override { return 0; }
+
+ virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) override {}
+ virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) override {}
+ virtual void soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {}
+
+ virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) override {}
+ virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const override { return Variant(); }
+
+ virtual void soft_body_set_transform(RID p_body, const Transform3D &p_transform) override {}
+
+ virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) override {}
+
+ virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) override {}
+ virtual int soft_body_get_simulation_precision(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) override {}
+ virtual real_t soft_body_get_total_mass(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) override {}
+ virtual real_t soft_body_get_linear_stiffness(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) override {}
+ virtual real_t soft_body_get_pressure_coefficient(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) override {}
+ virtual real_t soft_body_get_damping_coefficient(RID p_body) const override { return 0; }
+
+ virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) override {}
+ virtual real_t soft_body_get_drag_coefficient(RID p_body) const override { return 0; }
+
+ virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) override {}
+ virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) const override { return Vector3(); }
+
+ virtual void soft_body_remove_all_pinned_points(RID p_body) override {}
+ virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) override {}
+ virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) const override { return false; }
+
+ /* JOINT API */
+
+ virtual RID joint_create() override { return RID(); }
+
+ virtual void joint_clear(RID p_joint) override {}
+
+ virtual JointType joint_get_type(RID p_joint) const override { return JointType::JOINT_TYPE_PIN; }
+
+ virtual void joint_set_solver_priority(RID p_joint, int p_priority) override {}
+ virtual int joint_get_solver_priority(RID p_joint) const override { return 0; }
+
+ virtual void joint_disable_collisions_between_bodies(RID p_joint, bool p_disable) override {}
+ virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const override { return false; }
+
+ virtual void joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override {}
+
+ virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override {}
+ virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override { return 0; }
+
+ virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) override {}
+ virtual Vector3 pin_joint_get_local_a(RID p_joint) const override { return Vector3(); }
+
+ virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) override {}
+ virtual Vector3 pin_joint_get_local_b(RID p_joint) const override { return Vector3(); }
+
+ virtual void joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_hinge_A, RID p_body_B, const Transform3D &p_hinge_B) override {}
+ virtual void joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override {}
+
+ virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override {}
+ virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const override { return 0; }
+
+ virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_enabled) override {}
+ virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override { return false; }
+
+ virtual void joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override {}
+
+ virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override {}
+ virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override { return 0; }
+
+ virtual void joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override {}
+
+ virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override {}
+ virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override { return 0; }
+
+ virtual void joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) override {}
+
+ virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) override {}
+ virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) const override { return 0; }
+
+ virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) override {}
+ virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) const override { return false; }
+
+ /* MISC */
+
+ virtual void free(RID p_rid) override {}
+
+ virtual void set_active(bool p_active) override {}
+ virtual void init() override {
+ space_state_dummy = memnew(PhysicsDirectSpaceState3DDummy);
+ body_state_dummy = memnew(PhysicsDirectBodyState3DDummy(space_state_dummy));
+ }
+ virtual void step(real_t p_step) override {}
+ virtual void sync() override {}
+ virtual void flush_queries() override {}
+ virtual void end_sync() override {}
+ virtual void finish() override {
+ memdelete(body_state_dummy);
+ memdelete(space_state_dummy);
+ }
+
+ virtual bool is_flushing_queries() const override { return false; }
+
+ virtual int get_process_info(ProcessInfo p_info) override { return 0; }
+};
+
+#endif // PHYSICS_SERVER_3D_DUMMY_H
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index fc2aae10c7..b23c77aa0a 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -89,8 +89,8 @@
// 3D physics and navigation (3D navigation is needed for 2D).
#include "navigation_server_3d.h"
#ifndef _3D_DISABLED
-#include "physics_3d/godot_physics_server_3d.h"
#include "physics_server_3d.h"
+#include "physics_server_3d_dummy.h"
#include "physics_server_3d_wrap_mt.h"
#include "servers/extensions/physics_server_3d_extension.h"
#include "xr/xr_body_tracker.h"
@@ -106,16 +106,8 @@
ShaderTypes *shader_types = nullptr;
#ifndef _3D_DISABLED
-static PhysicsServer3D *_createGodotPhysics3DCallback() {
-#ifdef THREADS_ENABLED
- bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread");
-#else
- bool using_threads = false;
-#endif
-
- PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads));
-
- return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads));
+static PhysicsServer3D *_create_dummy_physics_server_3d() {
+ return memnew(PhysicsServer3DDummy);
}
#endif // _3D_DISABLED
@@ -323,8 +315,7 @@ void register_server_types() {
GLOBAL_DEF(PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"), "DEFAULT");
- PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback));
- PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
+ PhysicsServer3DManager::get_singleton()->register_server("Dummy", callable_mp_static(_create_dummy_physics_server_3d));
GDREGISTER_ABSTRACT_CLASS(XRInterface);
GDREGISTER_CLASS(XRVRS);
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index c885ad52d1..0025fc5ab7 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -128,7 +128,7 @@ private:
h = hash_murmur3_one_32(p_val.layers, h);
h = hash_murmur3_one_32(p_val.mipmap, h);
h = hash_murmur3_one_32(p_val.mipmaps, h);
- h = hash_murmur3_one_32(p_val.texture_view.format_override);
+ h = hash_murmur3_one_32(p_val.texture_view.format_override, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_r, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_g, h);
h = hash_murmur3_one_32(p_val.texture_view.swizzle_b, h);
diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h
index 9ec1b812df..ef630ad4f7 100644
--- a/tests/scene/test_code_edit.h
+++ b/tests/scene/test_code_edit.h
@@ -4779,6 +4779,31 @@ TEST_CASE("[SceneTree][CodeEdit] text manipulation") {
CHECK(code_edit->get_caret_column(3) == 0);
}
+ SUBCASE("[SceneTree][CodeEdit] cut when empty selection clipboard disabled") {
+ DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton());
+ code_edit->set_empty_selection_clipboard_enabled(false);
+ DS->clipboard_set("");
+
+ code_edit->set_text("this is\nsome\n");
+ code_edit->set_caret_line(0);
+ code_edit->set_caret_column(6);
+ MessageQueue::get_singleton()->flush();
+ SIGNAL_DISCARD("text_set");
+ SIGNAL_DISCARD("text_changed");
+ SIGNAL_DISCARD("lines_edited_from");
+ SIGNAL_DISCARD("caret_changed");
+
+ code_edit->cut();
+ MessageQueue::get_singleton()->flush();
+ CHECK(DS->clipboard_get() == "");
+ CHECK(code_edit->get_text() == "this is\nsome\n");
+ CHECK(code_edit->get_caret_line() == 0);
+ CHECK(code_edit->get_caret_column() == 6);
+ SIGNAL_CHECK_FALSE("caret_changed");
+ SIGNAL_CHECK_FALSE("text_changed");
+ SIGNAL_CHECK_FALSE("lines_edited_from");
+ }
+
SUBCASE("[SceneTree][CodeEdit] new line") {
// Add a new line.
code_edit->set_text("test new line");
diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h
index 46a5046b21..c41eebdf3a 100644
--- a/tests/scene/test_text_edit.h
+++ b/tests/scene/test_text_edit.h
@@ -3585,6 +3585,54 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_CHECK_FALSE("lines_edited_from");
}
+ SUBCASE("[TextEdit] cut when empty selection clipboard disabled") {
+ text_edit->set_empty_selection_clipboard_enabled(false);
+ DS->clipboard_set("");
+
+ text_edit->set_text("this is\nsome\n");
+ text_edit->set_caret_line(0);
+ text_edit->set_caret_column(6);
+ MessageQueue::get_singleton()->flush();
+ SIGNAL_DISCARD("text_set");
+ SIGNAL_DISCARD("text_changed");
+ SIGNAL_DISCARD("lines_edited_from");
+ SIGNAL_DISCARD("caret_changed");
+
+ text_edit->cut();
+ MessageQueue::get_singleton()->flush();
+ CHECK(DS->clipboard_get() == "");
+ CHECK(text_edit->get_text() == "this is\nsome\n");
+ CHECK(text_edit->get_caret_line() == 0);
+ CHECK(text_edit->get_caret_column() == 6);
+ SIGNAL_CHECK_FALSE("caret_changed");
+ SIGNAL_CHECK_FALSE("text_changed");
+ SIGNAL_CHECK_FALSE("lines_edited_from");
+ }
+
+ SUBCASE("[TextEdit] copy when empty selection clipboard disabled") {
+ text_edit->set_empty_selection_clipboard_enabled(false);
+ DS->clipboard_set("");
+
+ text_edit->set_text("this is\nsome\n");
+ text_edit->set_caret_line(0);
+ text_edit->set_caret_column(6);
+ MessageQueue::get_singleton()->flush();
+ SIGNAL_DISCARD("text_set");
+ SIGNAL_DISCARD("text_changed");
+ SIGNAL_DISCARD("lines_edited_from");
+ SIGNAL_DISCARD("caret_changed");
+
+ text_edit->copy();
+ MessageQueue::get_singleton()->flush();
+ CHECK(DS->clipboard_get() == "");
+ CHECK(text_edit->get_text() == "this is\nsome\n");
+ CHECK(text_edit->get_caret_line() == 0);
+ CHECK(text_edit->get_caret_column() == 6);
+ SIGNAL_CHECK_FALSE("caret_changed");
+ SIGNAL_CHECK_FALSE("text_changed");
+ SIGNAL_CHECK_FALSE("lines_edited_from");
+ }
+
SIGNAL_UNWATCH(text_edit, "text_set");
SIGNAL_UNWATCH(text_edit, "text_changed");
SIGNAL_UNWATCH(text_edit, "lines_edited_from");
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 949e4f0b33..3c184ccc5d 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -176,6 +176,7 @@
#include "servers/physics_server_2d.h"
#ifndef _3D_DISABLED
#include "servers/physics_server_3d.h"
+#include "servers/physics_server_3d_dummy.h"
#endif // _3D_DISABLED
#include "servers/rendering/rendering_server_default.h"
@@ -290,6 +291,9 @@ struct GodotTestCaseListener : public doctest::IReporter {
#ifndef _3D_DISABLED
physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server();
+ if (!physics_server_3d) {
+ physics_server_3d = memnew(PhysicsServer3DDummy);
+ }
physics_server_3d->init();
#endif // _3D_DISABLED
diff --git a/thirdparty/README.md b/thirdparty/README.md
index a6686c539a..4c47b91c8c 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -614,7 +614,7 @@ to solve some MSVC warnings. See the patches in the `patches` directory.
## miniupnpc
- Upstream: https://github.com/miniupnp/miniupnp
-- Version: 2.2.7 (d4d5ec7d48c093b37b2ea5d7171ede21ce9d7ff2, 2024)
+- Version: 2.2.8 (b55145ec095652289a59c33603f3abafee898273, 2024)
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/miniupnpc/include/miniupnpc.h b/thirdparty/miniupnpc/include/miniupnpc.h
index 808c6ad975..fd951a0836 100644
--- a/thirdparty/miniupnpc/include/miniupnpc.h
+++ b/thirdparty/miniupnpc/include/miniupnpc.h
@@ -1,9 +1,9 @@
-/* $Id: miniupnpc.h,v 1.63 2024/01/04 00:45:17 nanard Exp $ */
+/* $Id: miniupnpc.h,v 1.66 2024/06/08 22:13:14 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project: miniupnp
* http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author: Thomas Bernard
- * Copyright (c) 2005-2022 Thomas Bernard
+ * Copyright (c) 2005-2024 Thomas Bernard
* This software is subjects to the conditions detailed
* in the LICENCE file provided within this distribution */
#ifndef MINIUPNPC_H_INCLUDED
@@ -20,8 +20,8 @@
#define UPNPDISCOVER_MEMORY_ERROR (-102)
/* versions : */
-#define MINIUPNPC_VERSION "2.2.6"
-#define MINIUPNPC_API_VERSION 17
+#define MINIUPNPC_VERSION "2.2.8"
+#define MINIUPNPC_API_VERSION 18
/* Source port:
Using "1" as an alias for 1900 for backwards compatibility
@@ -108,9 +108,11 @@ struct UPNPUrls {
* return values :
* 0 = NO IGD found
* 1 = A valid connected IGD has been found
- * 2 = A valid IGD has been found but it reported as
+ * 2 = A valid connected IGD has been found but its
+ * IP address is reserved (non routable)
+ * 3 = A valid IGD has been found but it reported as
* not connected
- * 3 = an UPnP device has been found but was not recognized as an IGD
+ * 4 = an UPnP device has been found but was not recognized as an IGD
*
* In any non zero return case, the urls and data structures
* passed as parameters are set. Donc forget to call FreeUPNPUrls(urls) to
@@ -119,8 +121,9 @@ struct UPNPUrls {
MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
- struct IGDdatas * data,
- char * lanaddr, int lanaddrlen);
+ struct IGDdatas * data,
+ char * lanaddr, int lanaddrlen,
+ char * wanaddr, int wanaddrlen);
/* UPNP_GetIGDFromUrl()
* Used when skipping the discovery process.
diff --git a/thirdparty/miniupnpc/src/addr_is_reserved.c b/thirdparty/miniupnpc/src/addr_is_reserved.c
index 18c6424201..145b504823 100644
--- a/thirdparty/miniupnpc/src/addr_is_reserved.c
+++ b/thirdparty/miniupnpc/src/addr_is_reserved.c
@@ -3,7 +3,7 @@
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2021 Thomas Bernard
+ * copyright (c) 2005-2024 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#ifdef _WIN32
@@ -21,6 +21,9 @@ typedef unsigned long uint32_t;
#include <netinet/in.h>
#include <arpa/inet.h>
#endif /* _WIN32 */
+#ifdef DEBUG
+#include <stdio.h>
+#endif
/* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */
#define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
@@ -71,8 +74,12 @@ int addr_is_reserved(const char * addr_str)
address = ntohl(addr_n);
for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) {
- if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask))
+ if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask)) {
+#ifdef DEBUG
+ printf("IP address %s is reserved\n", addr_str);
+#endif
return 1;
+ }
}
return 0;
diff --git a/thirdparty/miniupnpc/src/minisoap.c b/thirdparty/miniupnpc/src/minisoap.c
index 903ac5ffc6..5c6bf01684 100644
--- a/thirdparty/miniupnpc/src/minisoap.c
+++ b/thirdparty/miniupnpc/src/minisoap.c
@@ -2,7 +2,7 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Author : Thomas Bernard
- * Copyright (c) 2005-2023 Thomas Bernard
+ * Copyright (c) 2005-2024 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution.
*
@@ -83,7 +83,7 @@ int soapPostSubmit(SOCKET fd,
* Using HTTP/1.1 means we need to support chunked transfer-encoding :
* When using HTTP/1.1, the router "BiPAC 7404VNOX" always use chunked
* transfer encoding. */
- /* Connection: Close is normally there only in HTTP/1.1 but who knows */
+ /* Connection: close is normally there only in HTTP/1.1 but who knows */
portstr[0] = '\0';
if(port != 80)
snprintf(portstr, sizeof(portstr), ":%hu", port);
@@ -98,9 +98,8 @@ int soapPostSubmit(SOCKET fd,
"Content-Type: text/xml; charset=\"utf-8\"\r\n"
#endif
"SOAPAction: \"%s\"\r\n"
- "Connection: Close\r\n"
+ "Connection: close\r\n"
"Cache-Control: no-cache\r\n" /* ??? */
- "Pragma: no-cache\r\n"
"\r\n",
url, httpversion, host, portstr, bodysize, action);
if ((unsigned int)headerssize >= sizeof(headerbuf))
diff --git a/thirdparty/miniupnpc/src/minissdpc.c b/thirdparty/miniupnpc/src/minissdpc.c
index 98c5b37463..57cb99962e 100644
--- a/thirdparty/miniupnpc/src/minissdpc.c
+++ b/thirdparty/miniupnpc/src/minissdpc.c
@@ -1,9 +1,9 @@
-/* $Id: minissdpc.c,v 1.49 2021/05/13 11:00:36 nanard Exp $ */
+/* $Id: minissdpc.c,v 1.51 2024/05/16 00:12:05 nanard Exp $ */
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2021 Thomas Bernard
+ * copyright (c) 2005-2024 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENCE file. */
#include <stdio.h>
@@ -548,7 +548,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
#ifdef _WIN32
unsigned long _ttl = (unsigned long)ttl;
#endif
- int linklocal = 1;
+ int linklocal = 0; /* try first with site-local multicast */
int sentok;
if(error)
@@ -1007,9 +1007,10 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
/* switch linklocal flag */
if(linklocal) {
linklocal = 0;
- --deviceIndex;
} else {
+ /* try again with linklocal multicast */
linklocal = 1;
+ --deviceIndex;
}
}
}
diff --git a/thirdparty/miniupnpc/src/miniupnpc.c b/thirdparty/miniupnpc/src/miniupnpc.c
index 696af93237..9da1496b37 100644
--- a/thirdparty/miniupnpc/src/miniupnpc.c
+++ b/thirdparty/miniupnpc/src/miniupnpc.c
@@ -3,7 +3,7 @@
* Project : miniupnp
* Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas BERNARD
- * copyright (c) 2005-2021 Thomas Bernard
+ * copyright (c) 2005-2024 Thomas Bernard
* This software is subjet to the conditions detailed in the
* provided LICENSE file. */
#include <stdlib.h>
@@ -92,15 +92,15 @@ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGD
#endif
}
-/* simpleUPnPcommand2 :
+/* simpleUPnPcommand :
* not so simple !
* return values :
* pointer - OK
* NULL - error */
-static char *
-simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
- const char * action, struct UPNParg * args,
- int * bufsize, const char * httpversion)
+char *
+simpleUPnPcommand(int s, const char * url, const char * service,
+ const char * action, struct UPNParg * args,
+ int * bufsize)
{
char hostname[MAXHOSTNAMELEN+1];
unsigned short port = 0;
@@ -197,15 +197,15 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
return NULL;
}
if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
- if(ISINVALID(s)) {
+ if(ISINVALID((SOCKET)s)) {
s = connecthostport(hostname, port, 0);
- if(ISINVALID(s)) {
+ if(ISINVALID((SOCKET)s)) {
/* failed to connect */
return NULL;
}
}
- n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
+ n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, "1.1");
if(n<=0) {
#ifdef DEBUG
printf("Error sending SOAP request\n");
@@ -229,33 +229,6 @@ simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
return buf;
}
-/* simpleUPnPcommand :
- * not so simple !
- * return values :
- * pointer - OK
- * NULL - error */
-char *
-simpleUPnPcommand(int s, const char * url, const char * service,
- const char * action, struct UPNParg * args,
- int * bufsize)
-{
- char * buf;
-
-#if 1
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
-#else
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0");
- if (!buf || *bufsize == 0)
- {
-#if DEBUG
- printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
-#endif
- buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
- }
-#endif
- return buf;
-}
-
/* upnpDiscoverDevices() :
* return a chained list of all devices found or NULL if
* no devices was found.
@@ -534,9 +507,11 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
* -1 = Internal error
* 0 = NO IGD found
* 1 = A valid connected IGD has been found
- * 2 = A valid IGD has been found but it reported as
+ * 2 = A valid connected IGD has been found but its
+ * IP address is reserved (non routable)
+ * 3 = A valid IGD has been found but it reported as
* not connected
- * 3 = an UPnP device has been found but was not recognized as an IGD
+ * 4 = an UPnP device has been found but was not recognized as an IGD
*
* In any positive non zero return case, the urls and data structures
* passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to
@@ -545,11 +520,13 @@ UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
MINIUPNP_LIBSPEC int
UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPUrls * urls,
- struct IGDdatas * data,
- char * lanaddr, int lanaddrlen)
+ struct IGDdatas * data,
+ char * lanaddr, int lanaddrlen,
+ char * wanaddr, int wanaddrlen)
{
struct xml_desc {
char lanaddr[40];
+ char wanaddr[40];
char * xml;
int size;
int is_igd;
@@ -557,8 +534,8 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
struct UPNPDev * dev;
int ndev = 0;
int i;
- int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
- char extIpAddr[16];
+ int state = -1; /* state 1 : IGD connected. State 2 : connected with reserved IP.
+ * State 3 : IGD. State 4 : anything */
int status_code = -1;
if(!devlist)
@@ -602,7 +579,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
}
}
/* iterate the list to find a device depending on state */
- for(state = 1; state <= 3; state++)
+ for(state = 1; state <= 4; state++)
{
for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
{
@@ -611,14 +588,14 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
memset(data, 0, sizeof(struct IGDdatas));
memset(urls, 0, sizeof(struct UPNPUrls));
parserootdesc(desc[i].xml, desc[i].size, data);
- if(desc[i].is_igd || state >= 3 )
+ if(desc[i].is_igd || state >= 4 )
{
int is_connected;
GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
- /* in state 2 and 3 we don't test if device is connected ! */
- if(state >= 2)
+ /* in state 3 and 4 we don't test if device is connected ! */
+ if(state >= 3)
goto free_and_return;
is_connected = UPNPIGD_IsConnected(urls, data);
#ifdef DEBUG
@@ -626,9 +603,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
urls->controlURL, is_connected);
#endif
/* checks that status is connected AND there is a external IP address assigned */
- if(is_connected &&
- (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
- if(!addr_is_reserved(extIpAddr))
+ if(is_connected) {
+ if(state >= 2)
+ goto free_and_return;
+ if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0
+ && !addr_is_reserved(desc[i].wanaddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
@@ -647,9 +626,11 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
printf("UPNPIGD_IsConnected(%s) = %d\n",
urls->controlURL, is_connected);
#endif
- if(is_connected &&
- (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
- if(!addr_is_reserved(extIpAddr))
+ if(is_connected) {
+ if(state >= 2)
+ goto free_and_return;
+ if(UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, desc[i].wanaddr) == 0
+ && !addr_is_reserved(desc[i].wanaddr))
goto free_and_return;
}
FreeUPNPUrls(urls);
@@ -661,8 +642,12 @@ UPNP_GetValidIGD(struct UPNPDev * devlist,
}
state = 0;
free_and_return:
- if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev)
- strncpy(lanaddr, desc[i].lanaddr, lanaddrlen);
+ if (state >= 1 && state <= 4 && i < ndev) {
+ if (lanaddr != NULL)
+ strncpy(lanaddr, desc[i].lanaddr, lanaddrlen);
+ if (wanaddr != NULL)
+ strncpy(wanaddr, desc[i].wanaddr, wanaddrlen);
+ }
for(i = 0; i < ndev; i++)
free(desc[i].xml);
free(desc);
diff --git a/thirdparty/miniupnpc/src/miniupnpcstrings.h b/thirdparty/miniupnpc/src/miniupnpcstrings.h
index f5730111af..d40c2455ba 100644
--- a/thirdparty/miniupnpc/src/miniupnpcstrings.h
+++ b/thirdparty/miniupnpc/src/miniupnpcstrings.h
@@ -2,7 +2,7 @@
#define MINIUPNPCSTRINGS_H_INCLUDED
#define OS_STRING "Godot Engine/1.0"
-#define MINIUPNPC_VERSION_STRING "2.2.7"
+#define MINIUPNPC_VERSION_STRING "2.2.8"
#if 0
/* according to "UPnP Device Architecture 1.0" */
diff --git a/thirdparty/miniupnpc/src/miniwget.c b/thirdparty/miniupnpc/src/miniwget.c
index e76a5e516b..a7a32dfdba 100644
--- a/thirdparty/miniupnpc/src/miniwget.c
+++ b/thirdparty/miniupnpc/src/miniwget.c
@@ -2,7 +2,7 @@
/* Project : miniupnp
* Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
* Author : Thomas Bernard
- * Copyright (c) 2005-2023 Thomas Bernard
+ * Copyright (c) 2005-2024 Thomas Bernard
* This software is subject to the conditions detailed in the
* LICENCE file provided in this distribution. */
@@ -443,9 +443,8 @@ miniwget3(const char * host,
len = snprintf(buf, sizeof(buf),
"GET %s HTTP/%s\r\n"
"Host: %s:%d\r\n"
- "Connection: Close\r\n"
+ "Connection: close\r\n"
"User-Agent: " OS_STRING " " UPNP_VERSION_STRING " MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
-
"\r\n",
path, httpversion, host, port);
if ((unsigned int)len >= sizeof(buf))
@@ -474,41 +473,6 @@ miniwget3(const char * host,
return content;
}
-/* miniwget2() :
- * Call miniwget3(); retry with HTTP/1.1 if 1.0 fails. */
-static void *
-miniwget2(const char * host,
- unsigned short port, const char * path,
- int * size, char * addr_str, int addr_str_len,
- unsigned int scope_id, int * status_code)
-{
- char * respbuffer;
-
-#if 1
- respbuffer = miniwget3(host, port, path, size,
- addr_str, addr_str_len, "1.1",
- scope_id, status_code);
-#else
- respbuffer = miniwget3(host, port, path, size,
- addr_str, addr_str_len, "1.0",
- scope_id, status_code);
- if (*size == 0)
- {
-#ifdef DEBUG
- printf("Retrying with HTTP/1.1\n");
-#endif
- free(respbuffer);
- respbuffer = miniwget3(host, port, path, size,
- addr_str, addr_str_len, "1.1",
- scope_id, status_code);
- }
-#endif
- return respbuffer;
-}
-
-
-
-
/* parseURL()
* arguments :
* url : source string not modified
@@ -639,7 +603,7 @@ miniwget(const char * url, int * size,
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
- return miniwget2(hostname, port, path, size, 0, 0, scope_id, status_code);
+ return miniwget3(hostname, port, path, size, 0, 0, "1.1", scope_id, status_code);
}
void *
@@ -660,5 +624,5 @@ miniwget_getaddr(const char * url, int * size,
printf("parsed url : hostname='%s' port=%hu path='%s' scope_id=%u\n",
hostname, port, path, scope_id);
#endif
- return miniwget2(hostname, port, path, size, addr, addrlen, scope_id, status_code);
+ return miniwget3(hostname, port, path, size, addr, addrlen, "1.1", scope_id, status_code);
}
diff --git a/thirdparty/miniupnpc/src/win32_snprintf.h b/thirdparty/miniupnpc/src/win32_snprintf.h
index 1fc284ecff..5064df63bc 100644
--- a/thirdparty/miniupnpc/src/win32_snprintf.h
+++ b/thirdparty/miniupnpc/src/win32_snprintf.h
@@ -23,9 +23,9 @@
(defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \
(defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \
- (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \
+ (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0) /* ... with ansi stdio */ || \
(__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \
- (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \
+ (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT))) /* ... at least 8.0.0 with iso c ext */ || \
0) || \
0)