summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct15
-rw-r--r--core/config/engine.cpp8
-rw-r--r--core/config/engine.h24
-rw-r--r--core/core_bind.cpp19
-rw-r--r--core/core_bind.h15
-rw-r--r--core/core_constants.cpp47
-rw-r--r--core/debugger/debugger_marshalls.h16
-rw-r--r--core/debugger/engine_debugger.cpp2
-rw-r--r--core/debugger/engine_debugger.h12
-rw-r--r--core/debugger/local_debugger.cpp14
-rw-r--r--core/debugger/remote_debugger.cpp18
-rw-r--r--core/extension/extension_api_dump.cpp149
-rw-r--r--core/extension/gdnative_interface.cpp176
-rw-r--r--core/extension/gdnative_interface.h32
-rw-r--r--core/extension/native_extension.cpp25
-rw-r--r--core/extension/native_extension.h4
-rw-r--r--core/input/input_event.cpp24
-rw-r--r--core/input/input_event.h16
-rw-r--r--core/io/multiplayer_api.cpp186
-rw-r--r--core/io/multiplayer_api.h19
-rw-r--r--core/math/basis.cpp18
-rw-r--r--core/math/basis.h2
-rw-r--r--core/math/math_defs.h20
-rw-r--r--core/math/transform_3d.cpp32
-rw-r--r--core/object/class_db.cpp6
-rw-r--r--core/object/class_db.h2
-rw-r--r--core/object/object.cpp4
-rw-r--r--core/object/object.h1
-rw-r--r--core/register_core_types.cpp8
-rw-r--r--core/variant/binder_common.h1
-rw-r--r--core/variant/variant.cpp3
-rw-r--r--core/variant/variant.h12
-rw-r--r--core/variant/variant_call.cpp3
-rw-r--r--core/variant/variant_destruct.cpp78
-rw-r--r--core/variant/variant_destruct.h76
-rw-r--r--core/variant/variant_internal.h20
-rw-r--r--doc/classes/@GlobalScope.xml94
-rw-r--r--doc/classes/Basis.xml9
-rw-r--r--doc/classes/CharacterBody2D.xml42
-rw-r--r--doc/classes/CharacterBody3D.xml1
-rw-r--r--doc/classes/EditorCommandPalette.xml31
-rw-r--r--doc/classes/EditorInterface.xml5
-rw-r--r--doc/classes/MultiplayerAPI.xml89
-rw-r--r--doc/classes/NativeExtension.xml2
-rw-r--r--doc/classes/Node3D.xml7
-rw-r--r--doc/classes/PhysicsDirectBodyState2D.xml7
-rw-r--r--doc/classes/PhysicsDirectBodyState3D.xml7
-rw-r--r--doc/classes/PhysicsServer3D.xml2
-rw-r--r--doc/classes/RenderingDevice.xml6
-rw-r--r--doc/classes/ResourceLoader.xml7
-rw-r--r--doc/classes/RichTextLabel.xml4
-rw-r--r--doc/classes/TextLine.xml4
-rw-r--r--doc/classes/TextParagraph.xml4
-rw-r--r--doc/classes/TextServer.xml4
-rw-r--r--doc/classes/Transform2D.xml2
-rw-r--r--doc/classes/Transform3D.xml5
-rw-r--r--doc/classes/Viewport.xml2
-rw-r--r--drivers/windows/file_access_windows.cpp22
-rw-r--r--editor/editor_command_palette.cpp300
-rw-r--r--editor/editor_command_palette.h95
-rw-r--r--editor/editor_node.cpp127
-rw-r--r--editor/editor_node.h6
-rw-r--r--editor/editor_plugin.cpp5
-rw-r--r--editor/editor_plugin.h3
-rw-r--r--editor/editor_themes.cpp3
-rw-r--r--editor/icons/PrismMesh.svg2
-rw-r--r--editor/import/editor_import_collada.cpp4
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h4
-rw-r--r--editor/plugins/editor_preview_plugins.cpp8
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp16
-rw-r--r--editor/plugins/node_3d_editor_plugin.h6
-rw-r--r--editor/plugins/script_text_editor.cpp7
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp16
-rw-r--r--editor/property_selector.cpp47
-rw-r--r--editor/shader_create_dialog.cpp82
-rw-r--r--editor/shader_create_dialog.h2
-rw-r--r--modules/bullet/SCsub2
-rw-r--r--modules/bullet/bullet_physics_server.cpp4
-rw-r--r--modules/bullet/bullet_physics_server.h2
-rw-r--r--modules/bullet/godot_result_callbacks.cpp4
-rw-r--r--modules/bullet/godot_result_callbacks.h4
-rw-r--r--modules/bullet/rigid_body_bullet.cpp10
-rw-r--r--modules/bullet/rigid_body_bullet.h2
-rw-r--r--modules/bullet/space_bullet.cpp16
-rw-r--r--modules/bullet/space_bullet.h4
-rw-r--r--modules/csg/csg_shape.h4
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp4
-rw-r--r--modules/fbx/data/fbx_mesh_data.h2
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp22
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp17
-rw-r--r--modules/gdnative/text/text_server_gdnative.cpp4
-rw-r--r--modules/gdnative/text/text_server_gdnative.h4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp2
-rw-r--r--modules/gdscript/gdscript_parser.cpp4
-rw-r--r--modules/gltf/gltf_document.cpp12
-rw-r--r--modules/text_server_adv/text_server_adv.cpp258
-rw-r--r--modules/text_server_adv/text_server_adv.h4
-rw-r--r--modules/text_server_fb/text_server_fb.cpp258
-rw-r--r--modules/text_server_fb/text_server_fb.h4
-rw-r--r--modules/vhacd/register_types.cpp2
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp6
-rw-r--r--modules/visual_script/visual_script_yield_nodes.h6
-rw-r--r--platform/osx/display_server_osx.mm12
-rw-r--r--scene/2d/animated_sprite_2d.cpp16
-rw-r--r--scene/2d/animated_sprite_2d.h6
-rw-r--r--scene/2d/cpu_particles_2d.cpp48
-rw-r--r--scene/2d/cpu_particles_2d.h38
-rw-r--r--scene/2d/gpu_particles_2d.cpp29
-rw-r--r--scene/2d/gpu_particles_2d.h30
-rw-r--r--scene/2d/navigation_region_2d.cpp4
-rw-r--r--scene/2d/physics_body_2d.cpp366
-rw-r--r--scene/2d/physics_body_2d.h42
-rw-r--r--scene/2d/ray_cast_2d.cpp8
-rw-r--r--scene/2d/skeleton_2d.cpp20
-rw-r--r--scene/2d/skeleton_2d.h18
-rw-r--r--scene/3d/audio_stream_player_3d.cpp4
-rw-r--r--scene/3d/camera_3d.cpp42
-rw-r--r--scene/3d/camera_3d.h56
-rw-r--r--scene/3d/cpu_particles_3d.cpp176
-rw-r--r--scene/3d/cpu_particles_3d.h106
-rw-r--r--scene/3d/decal.cpp28
-rw-r--r--scene/3d/decal.h42
-rw-r--r--scene/3d/gpu_particles_3d.cpp12
-rw-r--r--scene/3d/gpu_particles_3d.h18
-rw-r--r--scene/3d/light_3d.cpp8
-rw-r--r--scene/3d/light_3d.h6
-rw-r--r--scene/3d/listener_3d.cpp16
-rw-r--r--scene/3d/node_3d.cpp26
-rw-r--r--scene/3d/node_3d.h12
-rw-r--r--scene/3d/path_3d.cpp34
-rw-r--r--scene/3d/path_3d.h16
-rw-r--r--scene/3d/physics_body_3d.cpp101
-rw-r--r--scene/3d/physics_body_3d.h4
-rw-r--r--scene/3d/proximity_group_3d.h2
-rw-r--r--scene/3d/skeleton_3d.cpp2
-rw-r--r--scene/3d/skeleton_3d.h4
-rw-r--r--scene/3d/skeleton_ik_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp14
-rw-r--r--scene/3d/sprite_3d.h8
-rw-r--r--scene/3d/velocity_tracker_3d.cpp12
-rw-r--r--scene/3d/voxelizer.cpp42
-rw-r--r--scene/3d/xr_nodes.cpp6
-rw-r--r--scene/3d/xr_nodes.h6
-rw-r--r--scene/animation/animation_blend_space_1d.cpp4
-rw-r--r--scene/animation/animation_blend_space_1d.h2
-rw-r--r--scene/animation/animation_blend_space_2d.cpp4
-rw-r--r--scene/animation/animation_blend_space_2d.h2
-rw-r--r--scene/animation/animation_blend_tree.cpp66
-rw-r--r--scene/animation/animation_blend_tree.h22
-rw-r--r--scene/animation/animation_node_state_machine.cpp4
-rw-r--r--scene/animation/animation_node_state_machine.h4
-rw-r--r--scene/animation/animation_player.cpp28
-rw-r--r--scene/animation/animation_player.h12
-rw-r--r--scene/animation/animation_tree.cpp66
-rw-r--r--scene/animation/animation_tree.h40
-rw-r--r--scene/animation/root_motion_view.h4
-rw-r--r--scene/debugger/scene_debugger.cpp8
-rw-r--r--scene/gui/base_button.cpp3
-rw-r--r--scene/gui/gradient_edit.cpp34
-rw-r--r--scene/gui/gradient_edit.h6
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/rich_text_effect.h6
-rw-r--r--scene/gui/rich_text_label.cpp78
-rw-r--r--scene/gui/rich_text_label.h12
-rw-r--r--scene/gui/shortcut.cpp8
-rw-r--r--scene/main/node.cpp11
-rw-r--r--scene/main/node.h5
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp901
-rw-r--r--scene/main/viewport.h152
-rw-r--r--scene/resources/animation.cpp238
-rw-r--r--scene/resources/animation.h114
-rw-r--r--scene/resources/curve.cpp8
-rw-r--r--scene/resources/curve.h4
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/default_theme/theme_data.h4
-rw-r--r--scene/resources/height_map_shape_3d.cpp18
-rw-r--r--scene/resources/height_map_shape_3d.h6
-rw-r--r--scene/resources/mesh.cpp2
-rw-r--r--scene/resources/mesh_data_tool.cpp4
-rw-r--r--scene/resources/polygon_path_finder.cpp8
-rw-r--r--scene/resources/resource_format_text.cpp12
-rw-r--r--scene/resources/sprite_frames.cpp4
-rw-r--r--scene/resources/sprite_frames.h6
-rw-r--r--scene/resources/text_line.cpp8
-rw-r--r--scene/resources/text_line.h4
-rw-r--r--scene/resources/text_paragraph.cpp8
-rw-r--r--scene/resources/text_paragraph.h4
-rw-r--r--scene/resources/visual_shader.cpp13
-rw-r--r--servers/physics_2d/body_2d_sw.h6
-rw-r--r--servers/physics_3d/body_3d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp4
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_wrap_mt.h4
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp18
-rw-r--r--servers/physics_3d/shape_3d_sw.h8
-rw-r--r--servers/physics_3d/space_3d_sw.cpp11
-rw-r--r--servers/physics_3d/space_3d_sw.h2
-rw-r--r--servers/physics_server_2d.cpp2
-rw-r--r--servers/physics_server_2d.h2
-rw-r--r--servers/physics_server_3d.cpp12
-rw-r--r--servers/physics_server_3d.h6
-rw-r--r--servers/rendering/rasterizer_dummy.h10
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp8
-rw-r--r--servers/rendering/renderer_compositor.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp15
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp22
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h20
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/tonemap.glsl10
-rw-r--r--servers/rendering/renderer_scene_cull.cpp4
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h2
-rw-r--r--servers/rendering/renderer_storage.h6
-rw-r--r--servers/rendering/rendering_device.cpp6
-rw-r--r--servers/rendering/rendering_server_default.cpp12
-rw-r--r--servers/rendering/rendering_server_default.h14
-rw-r--r--servers/rendering_server.cpp87
-rw-r--r--servers/rendering_server.h18
-rw-r--r--servers/text_server.cpp4
-rw-r--r--servers/text_server.h6
-rw-r--r--tests/test_math.cpp4
-rw-r--r--tests/test_render.cpp2
231 files changed, 4258 insertions, 2363 deletions
diff --git a/SConstruct b/SConstruct
index 45108721ad..0224784b9d 100644
--- a/SConstruct
+++ b/SConstruct
@@ -119,6 +119,7 @@ opts.Add(BoolVariable("tools", "Build the tools (a.k.a. the Godot editor)", True
opts.Add(EnumVariable("target", "Compilation target", "debug", ("debug", "release_debug", "release")))
opts.Add("arch", "Platform-dependent architecture (arm/arm64/x86/x64/mips/...)", "")
opts.Add(EnumVariable("bits", "Target platform bits", "default", ("default", "32", "64")))
+opts.Add(EnumVariable("float", "Floating-point precision", "default", ("default", "32", "64")))
opts.Add(EnumVariable("optimize", "Optimization type", "speed", ("speed", "size", "none")))
opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("use_lto", "Use link-time optimization", False))
@@ -201,7 +202,13 @@ elif env_base["p"] != "":
selected_platform = env_base["p"]
else:
# Missing `platform` argument, try to detect platform automatically
- if sys.platform.startswith("linux"):
+ if (
+ sys.platform.startswith("linux")
+ or sys.platform.startswith("dragonfly")
+ or sys.platform.startswith("freebsd")
+ or sys.platform.startswith("netbsd")
+ or sys.platform.startswith("openbsd")
+ ):
selected_platform = "linuxbsd"
elif sys.platform == "darwin":
selected_platform = "osx"
@@ -321,6 +328,9 @@ if env_base["no_editor_splash"]:
if not env_base["deprecated"]:
env_base.Append(CPPDEFINES=["DISABLE_DEPRECATED"])
+if env_base["float"] == "64":
+ env_base.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
+
if selected_platform in platform_list:
tmppath = "./platform/" + selected_platform
sys.path.insert(0, tmppath)
@@ -558,6 +568,9 @@ if selected_platform in platform_list:
else:
suffix = "." + selected_platform
+ if env_base["float"] == "64":
+ suffix += ".double"
+
if env["target"] == "release":
if env["tools"]:
print("Error: The editor can only be built with `target=debug` or `target=release_debug`.")
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index 0b5b5627af..3ffd8ee46b 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -46,14 +46,14 @@ int Engine::get_iterations_per_second() const {
return ips;
}
-void Engine::set_physics_jitter_fix(float p_threshold) {
+void Engine::set_physics_jitter_fix(double p_threshold) {
if (p_threshold < 0) {
p_threshold = 0;
}
physics_jitter_fix = p_threshold;
}
-float Engine::get_physics_jitter_fix() const {
+double Engine::get_physics_jitter_fix() const {
return physics_jitter_fix;
}
@@ -77,11 +77,11 @@ uint32_t Engine::get_frame_delay() const {
return _frame_delay;
}
-void Engine::set_time_scale(float p_scale) {
+void Engine::set_time_scale(double p_scale) {
_time_scale = p_scale;
}
-float Engine::get_time_scale() const {
+double Engine::get_time_scale() const {
return _time_scale;
}
diff --git a/core/config/engine.h b/core/config/engine.h
index 970cfb03e8..3b3e5825b2 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -51,15 +51,15 @@ private:
uint64_t frames_drawn = 0;
uint32_t _frame_delay = 0;
uint64_t _frame_ticks = 0;
- float _process_step = 0;
+ double _process_step = 0;
int ips = 60;
- float physics_jitter_fix = 0.5;
- float _fps = 1;
+ double physics_jitter_fix = 0.5;
+ double _fps = 1;
int _target_fps = 0;
- float _time_scale = 1.0;
+ double _time_scale = 1.0;
uint64_t _physics_frames = 0;
- float _physics_interpolation_fraction = 0.0f;
+ double _physics_interpolation_fraction = 0.0f;
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
@@ -81,13 +81,13 @@ public:
virtual void set_iterations_per_second(int p_ips);
virtual int get_iterations_per_second() const;
- void set_physics_jitter_fix(float p_threshold);
- float get_physics_jitter_fix() const;
+ void set_physics_jitter_fix(double p_threshold);
+ double get_physics_jitter_fix() const;
virtual void set_target_fps(int p_fps);
virtual int get_target_fps() const;
- virtual float get_frames_per_second() const { return _fps; }
+ virtual double get_frames_per_second() const { return _fps; }
uint64_t get_frames_drawn();
@@ -95,11 +95,11 @@ public:
uint64_t get_process_frames() const { return _process_frames; }
bool is_in_physics_frame() const { return _in_physics; }
uint64_t get_frame_ticks() const { return _frame_ticks; }
- float get_process_step() const { return _process_step; }
- float get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; }
+ double get_process_step() const { return _process_step; }
+ double get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; }
- void set_time_scale(float p_scale);
- float get_time_scale() const;
+ void set_time_scale(double p_scale);
+ double get_time_scale() const;
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 05fc309a28..76c918a92f 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -107,6 +107,10 @@ bool _ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
return ResourceLoader::exists(p_path, p_type_hint);
}
+ResourceUID::ID _ResourceLoader::get_resource_uid(const String &p_path) {
+ return ResourceLoader::get_resource_uid(p_path);
+}
+
void _ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &_ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false));
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &_ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
@@ -118,6 +122,7 @@ void _ResourceLoader::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &_ResourceLoader::get_dependencies);
ClassDB::bind_method(D_METHOD("has_cached", "path"), &_ResourceLoader::has_cached);
ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &_ResourceLoader::exists, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &_ResourceLoader::get_resource_uid);
BIND_ENUM_CONSTANT(THREAD_LOAD_INVALID_RESOURCE);
BIND_ENUM_CONSTANT(THREAD_LOAD_IN_PROGRESS);
@@ -2080,15 +2085,15 @@ int _Engine::get_iterations_per_second() const {
return Engine::get_singleton()->get_iterations_per_second();
}
-void _Engine::set_physics_jitter_fix(float p_threshold) {
+void _Engine::set_physics_jitter_fix(double p_threshold) {
Engine::get_singleton()->set_physics_jitter_fix(p_threshold);
}
-float _Engine::get_physics_jitter_fix() const {
+double _Engine::get_physics_jitter_fix() const {
return Engine::get_singleton()->get_physics_jitter_fix();
}
-float _Engine::get_physics_interpolation_fraction() const {
+double _Engine::get_physics_interpolation_fraction() const {
return Engine::get_singleton()->get_physics_interpolation_fraction();
}
@@ -2100,7 +2105,7 @@ int _Engine::get_target_fps() const {
return Engine::get_singleton()->get_target_fps();
}
-float _Engine::get_frames_per_second() const {
+double _Engine::get_frames_per_second() const {
return Engine::get_singleton()->get_frames_per_second();
}
@@ -2112,11 +2117,11 @@ uint64_t _Engine::get_process_frames() const {
return Engine::get_singleton()->get_process_frames();
}
-void _Engine::set_time_scale(float p_scale) {
+void _Engine::set_time_scale(double p_scale) {
Engine::get_singleton()->set_time_scale(p_scale);
}
-float _Engine::get_time_scale() {
+double _Engine::get_time_scale() {
return Engine::get_singleton()->get_time_scale();
}
@@ -2337,7 +2342,7 @@ void _EngineDebugger::call_add(void *p_user, const Array &p_data) {
ERR_FAIL_COND_MSG(err.error != Callable::CallError::CALL_OK, "Error calling 'add' to callable: " + Variant::get_callable_error_text(add, args, 1, err));
}
-void _EngineDebugger::call_tick(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+void _EngineDebugger::call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
Callable &tick = ((ProfilerCallable *)p_user)->callable_tick;
if (tick.is_null()) {
return;
diff --git a/core/core_bind.h b/core/core_bind.h
index 1574c36d3c..8736e6ffd8 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -75,6 +75,7 @@ public:
PackedStringArray get_dependencies(const String &p_path);
bool has_cached(const String &p_path);
bool exists(const String &p_path, const String &p_type_hint = "");
+ ResourceUID::ID get_resource_uid(const String &p_path);
_ResourceLoader() { singleton = this; }
};
@@ -625,21 +626,21 @@ public:
void set_iterations_per_second(int p_ips);
int get_iterations_per_second() const;
- void set_physics_jitter_fix(float p_threshold);
- float get_physics_jitter_fix() const;
- float get_physics_interpolation_fraction() const;
+ void set_physics_jitter_fix(double p_threshold);
+ double get_physics_jitter_fix() const;
+ double get_physics_interpolation_fraction() const;
void set_target_fps(int p_fps);
int get_target_fps() const;
- float get_frames_per_second() const;
+ double get_frames_per_second() const;
uint64_t get_physics_frames() const;
uint64_t get_process_frames() const;
int get_frames_drawn();
- void set_time_scale(float p_scale);
- float get_time_scale();
+ void set_time_scale(double p_scale);
+ double get_time_scale();
MainLoop *get_main_loop() const;
@@ -711,7 +712,7 @@ public:
static void call_toggle(void *p_user, bool p_enable, const Array &p_opts);
static void call_add(void *p_user, const Array &p_data);
- static void call_tick(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
+ static void call_tick(void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time);
static Error call_capture(void *p_user, const String &p_cmd, const Array &p_data, bool &r_captured);
_EngineDebugger() { singleton = this; }
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index de15cfd14a..b09e78d653 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -133,6 +133,19 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(VALIGN_CENTER);
BIND_CORE_ENUM_CONSTANT(VALIGN_BOTTOM);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TOP_TO);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_CENTER_TO);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_BOTTOM_TO);
+
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_TOP);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_CENTER);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_BASELINE);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TO_BOTTOM);
+
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_TOP);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_CENTER);
+ BIND_CORE_ENUM_CONSTANT(INLINE_ALIGN_BOTTOM);
+
// huge list of keys
BIND_CORE_CONSTANT(SPKEY);
@@ -532,8 +545,26 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_ID);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_VARIANT_TYPE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_BASE_TYPE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_INSTANCE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_METHOD_OF_SCRIPT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_BASE_TYPE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_INSTANCE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PROPERTY_OF_SCRIPT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_OBJECT_TOO_BIG);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_VALID_TYPES);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_SAVE_FILE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
+
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NETWORK);
@@ -549,6 +580,22 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORE_IF_NULL);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_ANIMATE_AS_TRIGGER);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CLASS_IS_ENUM);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NIL_IS_VARIANT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNAL);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_HIGH_END_GFX);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_KEYING_INCREMENTS);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFERRED_SET_RESOURCE);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_BASIC_SETTING);
+
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NOEDITOR);
diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h
index 3e8c34d84b..98ad2b98d1 100644
--- a/core/debugger/debugger_marshalls.h
+++ b/core/debugger/debugger_marshalls.h
@@ -83,14 +83,14 @@ struct DebuggerMarshalls {
StringName name;
int sig_id = -1;
int call_count = 0;
- float self_time = 0;
- float total_time = 0;
+ double self_time = 0;
+ double total_time = 0;
};
// Servers profiler
struct ServerFunctionInfo {
StringName name;
- float time = 0;
+ double time = 0;
};
struct ServerInfo {
@@ -100,11 +100,11 @@ struct DebuggerMarshalls {
struct ServersProfilerFrame {
int frame_number = 0;
- float frame_time = 0;
- float idle_time = 0;
- float physics_time = 0;
- float physics_frame_time = 0;
- float script_time = 0;
+ double frame_time = 0;
+ double idle_time = 0;
+ double physics_time = 0;
+ double physics_frame_time = 0;
+ double script_time = 0;
List<ServerInfo> servers;
Vector<ScriptFunctionInfo> script_functions;
diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp
index e5dba029c9..a522b1310f 100644
--- a/core/debugger/engine_debugger.cpp
+++ b/core/debugger/engine_debugger.cpp
@@ -117,7 +117,7 @@ void EngineDebugger::line_poll() {
poll_every++;
}
-void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time) {
+void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, double p_physics_frame_time) {
frame_time = USEC_TO_SEC(p_frame_ticks);
process_time = USEC_TO_SEC(p_process_ticks);
physics_time = USEC_TO_SEC(p_physics_ticks);
diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h
index c6daea6e2f..22c6ef943e 100644
--- a/core/debugger/engine_debugger.h
+++ b/core/debugger/engine_debugger.h
@@ -44,7 +44,7 @@ class ScriptDebugger;
class EngineDebugger {
public:
typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts);
- typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_process_time, float p_physics_time, float p_physics_frame_time);
+ typedef void (*ProfilingTick)(void *p_user, double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time);
typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr);
typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
@@ -85,10 +85,10 @@ public:
};
private:
- float frame_time = 0.0;
- float process_time = 0.0;
- float physics_time = 0.0;
- float physics_frame_time = 0.0;
+ double frame_time = 0.0;
+ double process_time = 0.0;
+ double physics_time = 0.0;
+ double physics_frame_time = 0.0;
uint32_t poll_every = 0;
@@ -120,7 +120,7 @@ public:
static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func);
- void iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time);
+ void iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, double p_physics_frame_time);
void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array());
Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured);
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index 24833711d5..b0b3f11424 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -41,7 +41,7 @@ struct LocalDebugger::ScriptsProfiler {
}
};
- float frame_time = 0;
+ double frame_time = 0;
uint64_t idle_accum = 0;
Vector<ScriptLanguage::ProfilingInfo> pinfo;
@@ -61,7 +61,7 @@ struct LocalDebugger::ScriptsProfiler {
}
}
- void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
frame_time = p_frame_time;
_print_frame_data(false);
}
@@ -92,8 +92,8 @@ struct LocalDebugger::ScriptsProfiler {
for (int i = 0; i < ofs; i++) {
script_time_us += pinfo[i].self_time;
}
- float script_time = USEC_TO_SEC(script_time_us);
- float total_time = p_accumulated ? script_time : frame_time;
+ double script_time = USEC_TO_SEC(script_time_us);
+ double total_time = p_accumulated ? script_time : frame_time;
if (!p_accumulated) {
print_line("FRAME: total: " + rtos(total_time) + " script: " + rtos(script_time) + "/" + itos(script_time * 100 / total_time) + " %");
@@ -103,8 +103,8 @@ struct LocalDebugger::ScriptsProfiler {
for (int i = 0; i < ofs; i++) {
print_line(itos(i) + ":" + pinfo[i].signature);
- float tt = USEC_TO_SEC(pinfo[i].total_time);
- float st = USEC_TO_SEC(pinfo[i].self_time);
+ double tt = USEC_TO_SEC(pinfo[i].total_time);
+ double st = USEC_TO_SEC(pinfo[i].self_time);
print_line("\ttotal: " + rtos(tt) + "/" + itos(tt * 100 / total_time) + " % \tself: " + rtos(st) + "/" + itos(st * 100 / total_time) + " % tcalls: " + itos(pinfo[i].call_count));
}
}
@@ -373,7 +373,7 @@ LocalDebugger::LocalDebugger() {
((ScriptsProfiler *)p_user)->toggle(p_enable, p_opts);
},
nullptr,
- [](void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ [](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
((ScriptsProfiler *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
});
register_profiler("scripts", scr_prof);
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index 62d5126e57..f865dfe102 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -50,7 +50,7 @@ void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) {
[](void *p_user, const Array &p_data) {
((T *)p_user)->add(p_data);
},
- [](void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ [](void *p_user, double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
((T *)p_user)->tick(p_frame_time, p_idle_time, p_physics_time, p_physics_frame_time);
});
EngineDebugger::register_profiler(p_name, prof);
@@ -164,7 +164,7 @@ public:
}
}
- void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
uint64_t pt = OS::get_singleton()->get_ticks_msec();
if (pt - last_bandwidth_time > 200) {
last_bandwidth_time = pt;
@@ -278,10 +278,10 @@ struct RemoteDebugger::ServersProfiler {
Map<StringName, ServerInfo> server_data;
ScriptsProfiler scripts_profiler;
- float frame_time = 0;
- float idle_time = 0;
- float physics_time = 0;
- float physics_frame_time = 0;
+ double frame_time = 0;
+ double idle_time = 0;
+ double physics_time = 0;
+ double physics_frame_time = 0;
void toggle(bool p_enable, const Array &p_opts) {
skip_profile_frame = false;
@@ -308,7 +308,7 @@ struct RemoteDebugger::ServersProfiler {
srv.functions.push_back(fi);
}
- void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
frame_time = p_frame_time;
idle_time = p_idle_time;
physics_time = p_physics_time;
@@ -358,7 +358,7 @@ struct RemoteDebugger::VisualProfiler {
void add(const Array &p_data) {}
- void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
Vector<RS::FrameProfileArea> profile_areas = RS::get_singleton()->get_frame_profile();
DebuggerMarshalls::VisualProfilerFrame frame;
if (!profile_areas.size()) {
@@ -378,7 +378,7 @@ struct RemoteDebugger::PerformanceProfiler {
void toggle(bool p_enable, const Array &p_opts) {}
void add(const Array &p_data) {}
- void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
+ void tick(double p_frame_time, double p_idle_time, double p_physics_time, double p_physics_frame_time) {
if (!performance) {
return;
}
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 660e215478..49570cd1c1 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -38,6 +38,25 @@
#ifdef TOOLS_ENABLED
+static String get_type_name(const PropertyInfo &p_info) {
+ if (p_info.type == Variant::INT && (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM)) {
+ return String("enum::") + String(p_info.class_name);
+ }
+ if (p_info.class_name != StringName()) {
+ return p_info.class_name;
+ }
+ if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ return p_info.hint_string;
+ }
+ if (p_info.type == Variant::NIL && (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) {
+ return "Variant";
+ }
+ if (p_info.type == Variant::NIL) {
+ return "void";
+ }
+ return Variant::get_type_name(p_info.type);
+}
+
Dictionary NativeExtensionAPIDump::generate_extension_api() {
Dictionary api_dump;
@@ -60,20 +79,38 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
const uint32_t vec3_elems = 3;
const uint32_t ptrsize_32 = 4;
- const uint32_t ptrsize_64 = 4;
+ const uint32_t ptrsize_64 = 8;
static const char *build_config_name[4] = { "float_32", "float_64", "double_32", "double_64" };
{
//type sizes
- struct {
+ constexpr struct {
Variant::Type type;
uint32_t size_32_bits_real_float;
uint32_t size_64_bits_real_float;
uint32_t size_32_bits_real_double;
uint32_t size_64_bits_real_double;
+
+ // For compile-time size check.
+ constexpr uint32_t operator[](int index) const {
+ switch (index) {
+#ifndef REAL_T_IS_DOUBLE
+ case sizeof(uint32_t):
+ return size_32_bits_real_float;
+ case sizeof(uint64_t):
+ return size_64_bits_real_float;
+#else // REAL_T_IS_DOUBLE
+ case sizeof(uint32_t):
+ return size_32_bits_real_double;
+ case sizeof(uint64_t):
+ return size_64_bits_real_double;
+#endif
+ }
+ return -1;
+ }
} type_size_array[Variant::VARIANT_MAX + 1] = {
{ Variant::NIL, 0, 0, 0, 0 },
- { Variant::BOOL, sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) },
+ { Variant::BOOL, sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t), sizeof(uint8_t) },
{ Variant::INT, sizeof(int64_t), sizeof(int64_t), sizeof(int64_t), sizeof(int64_t) },
{ Variant::FLOAT, sizeof(double), sizeof(double), sizeof(double), sizeof(double) },
{ Variant::STRING, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
@@ -98,25 +135,62 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, // Hardcoded align.
{ Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
{ Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_BYTE_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_INT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_INT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_STRING_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::PACKED_COLOR_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
+ { Variant::PACKED_BYTE_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_INT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_INT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_FLOAT32_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_FLOAT64_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_STRING_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_VECTOR2_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_VECTOR3_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
+ { Variant::PACKED_COLOR_ARRAY, ptrsize_32 * 2, ptrsize_64 * 2, ptrsize_32 * 2, ptrsize_64 * 2 },
{ Variant::VARIANT_MAX, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(float) * 4, sizeof(uint64_t) + sizeof(double) * 4, sizeof(uint64_t) + sizeof(double) * 4 },
};
+ // Validate sizes at compile time for the current build configuration.
+ static_assert(type_size_array[Variant::BOOL][sizeof(void *)] == sizeof(GDNativeBool), "Size of bool mismatch");
+ static_assert(type_size_array[Variant::INT][sizeof(void *)] == sizeof(GDNativeInt), "Size of int mismatch");
+ static_assert(type_size_array[Variant::FLOAT][sizeof(void *)] == sizeof(double), "Size of float mismatch");
+ static_assert(type_size_array[Variant::STRING][sizeof(void *)] == sizeof(String), "Size of String mismatch");
+ static_assert(type_size_array[Variant::VECTOR2][sizeof(void *)] == sizeof(Vector2), "Size of Vector2 mismatch");
+ static_assert(type_size_array[Variant::VECTOR2I][sizeof(void *)] == sizeof(Vector2i), "Size of Vector2i mismatch");
+ static_assert(type_size_array[Variant::RECT2][sizeof(void *)] == sizeof(Rect2), "Size of Rect2 mismatch");
+ static_assert(type_size_array[Variant::RECT2I][sizeof(void *)] == sizeof(Rect2i), "Size of Rect2i mismatch");
+ static_assert(type_size_array[Variant::VECTOR3][sizeof(void *)] == sizeof(Vector3), "Size of Vector3 mismatch");
+ static_assert(type_size_array[Variant::VECTOR3I][sizeof(void *)] == sizeof(Vector3i), "Size of Vector3i mismatch");
+ static_assert(type_size_array[Variant::TRANSFORM2D][sizeof(void *)] == sizeof(Transform2D), "Size of Transform2D mismatch");
+ static_assert(type_size_array[Variant::PLANE][sizeof(void *)] == sizeof(Plane), "Size of Plane mismatch");
+ static_assert(type_size_array[Variant::QUATERNION][sizeof(void *)] == sizeof(Quaternion), "Size of Quaternion mismatch");
+ static_assert(type_size_array[Variant::AABB][sizeof(void *)] == sizeof(AABB), "Size of AABB mismatch");
+ static_assert(type_size_array[Variant::BASIS][sizeof(void *)] == sizeof(Basis), "Size of Basis mismatch");
+ static_assert(type_size_array[Variant::TRANSFORM3D][sizeof(void *)] == sizeof(Transform3D), "Size of Transform3D mismatch");
+ static_assert(type_size_array[Variant::COLOR][sizeof(void *)] == sizeof(Color), "Size of Color mismatch");
+ static_assert(type_size_array[Variant::STRING_NAME][sizeof(void *)] == sizeof(StringName), "Size of StringName mismatch");
+ static_assert(type_size_array[Variant::NODE_PATH][sizeof(void *)] == sizeof(NodePath), "Size of NodePath mismatch");
+ static_assert(type_size_array[Variant::RID][sizeof(void *)] == sizeof(RID), "Size of RID mismatch");
+ static_assert(type_size_array[Variant::OBJECT][sizeof(void *)] == sizeof(Object *), "Size of Object mismatch");
+ static_assert(type_size_array[Variant::CALLABLE][sizeof(void *)] == sizeof(Callable), "Size of Callable mismatch");
+ static_assert(type_size_array[Variant::SIGNAL][sizeof(void *)] == sizeof(Signal), "Size of Signal mismatch");
+ static_assert(type_size_array[Variant::DICTIONARY][sizeof(void *)] == sizeof(Dictionary), "Size of Dictionary mismatch");
+ static_assert(type_size_array[Variant::ARRAY][sizeof(void *)] == sizeof(Array), "Size of Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_BYTE_ARRAY][sizeof(void *)] == sizeof(PackedByteArray), "Size of PackedByteArray mismatch");
+ static_assert(type_size_array[Variant::PACKED_INT32_ARRAY][sizeof(void *)] == sizeof(PackedInt32Array), "Size of PackedInt32Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_INT64_ARRAY][sizeof(void *)] == sizeof(PackedInt64Array), "Size of PackedInt64Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_FLOAT32_ARRAY][sizeof(void *)] == sizeof(PackedFloat32Array), "Size of PackedFloat32Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_FLOAT64_ARRAY][sizeof(void *)] == sizeof(PackedFloat64Array), "Size of PackedFloat64Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_STRING_ARRAY][sizeof(void *)] == sizeof(PackedStringArray), "Size of PackedStringArray mismatch");
+ static_assert(type_size_array[Variant::PACKED_VECTOR2_ARRAY][sizeof(void *)] == sizeof(PackedVector2Array), "Size of PackedVector2Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_VECTOR3_ARRAY][sizeof(void *)] == sizeof(PackedVector3Array), "Size of PackedVector3Array mismatch");
+ static_assert(type_size_array[Variant::PACKED_COLOR_ARRAY][sizeof(void *)] == sizeof(PackedColorArray), "Size of PackedColorArray mismatch");
+ static_assert(type_size_array[Variant::VARIANT_MAX][sizeof(void *)] == sizeof(Variant), "Size of Variant mismatch");
+
Array core_type_sizes;
for (int i = 0; i < 4; i++) {
Dictionary d;
d["build_configuration"] = build_config_name[i];
Array sizes;
- for (int j = 0; j < Variant::VARIANT_MAX; j++) {
+ for (int j = 0; j <= Variant::VARIANT_MAX; j++) {
Variant::Type t = type_size_array[j].type;
String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t);
Dictionary d2;
@@ -356,6 +430,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
d["indexing_return_type"] = index_type == Variant::NIL ? String("Variant") : Variant::get_type_name(index_type);
}
+ d["is_keyed"] = Variant::ValidatedKeyedSetter(type);
+
{
//members
Array members;
@@ -403,6 +479,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
d2["right_type"] = Variant::get_type_name(Variant::Type(j));
}
+ d2["return_type"] = Variant::get_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j)));
operators.push_back(d2);
}
}
@@ -482,6 +559,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
d["constructors"] = constructors;
}
}
+ {
+ //destructor
+ d["has_destructor"] = Variant::has_destructor(type);
+ }
builtins.push_back(d);
}
@@ -590,16 +671,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
if (i >= 0) {
d3["name"] = pinfo.name;
}
- if (pinfo.class_name != StringName()) {
- d3["type"] = String(pinfo.class_name);
- } else {
- Variant::Type type = pinfo.type;
- if (type == Variant::NIL) {
- d3["type"] = "Variant";
- } else {
- d3["type"] = Variant::get_type_name(type);
- }
- }
+
+ d3["type"] = get_type_name(pinfo);
if (i == -1) {
d2["return_value"] = d3;
@@ -641,16 +714,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
if (i >= 0) {
d3["name"] = pinfo.name;
}
- if (pinfo.class_name != StringName()) {
- d3["type"] = String(pinfo.class_name);
- } else {
- Variant::Type type = pinfo.type;
- if (type == Variant::NIL) {
- d3["type"] = "Variant";
- } else {
- d3["type"] = Variant::get_type_name(type);
- }
- }
+ d3["type"] = get_type_name(pinfo);
if (method->get_argument_meta(i) > 0) {
static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
@@ -697,14 +761,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
for (int i = 0; i < F.arguments.size(); i++) {
Dictionary d3;
d3["name"] = F.arguments[i].name;
- Variant::Type type = F.arguments[i].type;
- if (F.arguments[i].class_name != StringName()) {
- d3["type"] = String(F.arguments[i].class_name);
- } else if (type == Variant::NIL) {
- d3["type"] = "Variant";
- } else {
- d3["type"] = Variant::get_type_name(type);
- }
+ d3["type"] = get_type_name(F.arguments[i]);
arguments.push_back(d3);
}
if (arguments.size()) {
@@ -732,16 +789,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
}
StringName property_name = F.name;
Dictionary d2;
+ d2["type"] = get_type_name(F);
d2["name"] = String(property_name);
-
- if (F.class_name != StringName()) {
- d2["type"] = String(F.class_name);
- } else if (F.type == Variant::NIL && F.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
- d2["type"] = "Variant";
- } else {
- d2["type"] = Variant::get_type_name(F.type);
- }
-
d2["setter"] = ClassDB::get_property_setter(class_name, F.name);
d2["getter"] = ClassDB::get_property_getter(class_name, F.name);
d2["index"] = ClassDB::get_property_index(class_name, F.name);
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index 88fff342ee..a444b2e18e 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -299,6 +299,161 @@ static GDNativeBool gdnative_variant_can_convert_strict(GDNativeVariantType p_fr
return Variant::can_convert_strict((Variant::Type)p_from, (Variant::Type)p_to);
}
+// Variant interaction.
+static GDNativeVariantFromTypeConstructorFunc gdnative_get_variant_from_type_constructor(GDNativeVariantType p_type) {
+ switch (p_type) {
+ case GDNATIVE_VARIANT_TYPE_BOOL:
+ return VariantTypeConstructor<bool>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_INT:
+ return VariantTypeConstructor<int64_t>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_FLOAT:
+ return VariantTypeConstructor<double>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_STRING:
+ return VariantTypeConstructor<String>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR2:
+ return VariantTypeConstructor<Vector2>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR2I:
+ return VariantTypeConstructor<Vector2i>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_RECT2:
+ return VariantTypeConstructor<Rect2>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_RECT2I:
+ return VariantTypeConstructor<Rect2i>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR3:
+ return VariantTypeConstructor<Vector3>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_VECTOR3I:
+ return VariantTypeConstructor<Vector3i>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
+ return VariantTypeConstructor<Transform2D>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PLANE:
+ return VariantTypeConstructor<Plane>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_QUATERNION:
+ return VariantTypeConstructor<Quaternion>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_AABB:
+ return VariantTypeConstructor<AABB>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_BASIS:
+ return VariantTypeConstructor<Basis>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
+ return VariantTypeConstructor<Transform3D>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_COLOR:
+ return VariantTypeConstructor<Color>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_STRING_NAME:
+ return VariantTypeConstructor<StringName>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_NODE_PATH:
+ return VariantTypeConstructor<NodePath>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_RID:
+ return VariantTypeConstructor<RID>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_OBJECT:
+ return VariantTypeConstructor<Object *>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_CALLABLE:
+ return VariantTypeConstructor<Callable>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_SIGNAL:
+ return VariantTypeConstructor<Signal>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_DICTIONARY:
+ return VariantTypeConstructor<Dictionary>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_ARRAY:
+ return VariantTypeConstructor<Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
+ return VariantTypeConstructor<PackedByteArray>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
+ return VariantTypeConstructor<PackedInt32Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
+ return VariantTypeConstructor<PackedInt64Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
+ return VariantTypeConstructor<PackedFloat32Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
+ return VariantTypeConstructor<PackedFloat64Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
+ return VariantTypeConstructor<PackedStringArray>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
+ return VariantTypeConstructor<PackedVector2Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
+ return VariantTypeConstructor<PackedVector3Array>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
+ return VariantTypeConstructor<PackedColorArray>::variant_from_type;
+ case GDNATIVE_VARIANT_TYPE_NIL:
+ case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+ }
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+}
+
+static GDNativeTypeFromVariantConstructorFunc gdnative_get_type_from_variant_constructor(GDNativeVariantType p_type) {
+ switch (p_type) {
+ case GDNATIVE_VARIANT_TYPE_BOOL:
+ return VariantTypeConstructor<bool>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_INT:
+ return VariantTypeConstructor<int64_t>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_FLOAT:
+ return VariantTypeConstructor<double>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_STRING:
+ return VariantTypeConstructor<String>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR2:
+ return VariantTypeConstructor<Vector2>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR2I:
+ return VariantTypeConstructor<Vector2i>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_RECT2:
+ return VariantTypeConstructor<Rect2>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_RECT2I:
+ return VariantTypeConstructor<Rect2i>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR3:
+ return VariantTypeConstructor<Vector3>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_VECTOR3I:
+ return VariantTypeConstructor<Vector3i>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_TRANSFORM2D:
+ return VariantTypeConstructor<Transform2D>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PLANE:
+ return VariantTypeConstructor<Plane>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_QUATERNION:
+ return VariantTypeConstructor<Quaternion>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_AABB:
+ return VariantTypeConstructor<AABB>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_BASIS:
+ return VariantTypeConstructor<Basis>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_TRANSFORM3D:
+ return VariantTypeConstructor<Transform3D>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_COLOR:
+ return VariantTypeConstructor<Color>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_STRING_NAME:
+ return VariantTypeConstructor<StringName>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_NODE_PATH:
+ return VariantTypeConstructor<NodePath>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_RID:
+ return VariantTypeConstructor<RID>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_OBJECT:
+ return VariantTypeConstructor<Object *>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_CALLABLE:
+ return VariantTypeConstructor<Callable>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_SIGNAL:
+ return VariantTypeConstructor<Signal>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_DICTIONARY:
+ return VariantTypeConstructor<Dictionary>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_ARRAY:
+ return VariantTypeConstructor<Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_BYTE_ARRAY:
+ return VariantTypeConstructor<PackedByteArray>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_INT32_ARRAY:
+ return VariantTypeConstructor<PackedInt32Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_INT64_ARRAY:
+ return VariantTypeConstructor<PackedInt64Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT32_ARRAY:
+ return VariantTypeConstructor<PackedFloat32Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_FLOAT64_ARRAY:
+ return VariantTypeConstructor<PackedFloat64Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_STRING_ARRAY:
+ return VariantTypeConstructor<PackedStringArray>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR2_ARRAY:
+ return VariantTypeConstructor<PackedVector2Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_VECTOR3_ARRAY:
+ return VariantTypeConstructor<PackedVector3Array>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_PACKED_COLOR_ARRAY:
+ return VariantTypeConstructor<PackedColorArray>::type_from_variant;
+ case GDNATIVE_VARIANT_TYPE_NIL:
+ case GDNATIVE_VARIANT_TYPE_VARIANT_MAX:
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+ }
+ ERR_FAIL_V_MSG(nullptr, "Getting Variant conversion function with invalid type");
+}
+
// ptrcalls
static GDNativePtrOperatorEvaluator gdnative_variant_get_ptr_operator_evaluator(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b) {
return (GDNativePtrOperatorEvaluator)Variant::get_ptr_operator_evaluator(Variant::Operator(p_operator), Variant::Type(p_type_a), Variant::Type(p_type_b));
@@ -316,6 +471,9 @@ static GDNativePtrBuiltInMethod gdnative_variant_get_ptr_builtin_method(GDNative
static GDNativePtrConstructor gdnative_variant_get_ptr_constructor(GDNativeVariantType p_type, int32_t p_constructor) {
return (GDNativePtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
}
+static GDNativePtrDestructor gdnative_variant_get_ptr_destructor(GDNativeVariantType p_type) {
+ return (GDNativePtrDestructor)Variant::get_ptr_destructor(Variant::Type(p_type));
+}
static void gdnative_variant_construct(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error) {
memnew_placement(p_base, Variant);
@@ -521,11 +679,16 @@ static GDNativeObjectPtr gdnative_global_get_singleton(const char *p_name) {
return (GDNativeObjectPtr)Engine::get_singleton()->get_singleton_object(String(p_name));
}
-static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks) {
+static void *gdnative_object_get_instance_binding(GDNativeObjectPtr p_instance, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
Object *o = (Object *)p_instance;
return o->get_instance_binding(p_token, p_callbacks);
}
+static void gdnative_object_set_instance_binding(GDNativeObjectPtr p_instance, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ Object *o = (Object *)p_instance;
+ o->set_instance_binding(p_token, p_binding, p_callbacks);
+}
+
static GDNativeObjectPtr gdnative_object_get_instance_from_id(GDObjectInstanceID p_instance_id) {
return (GDNativeObjectPtr)ObjectDB::get_instance(ObjectID(p_instance_id));
}
@@ -626,15 +789,15 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.variant_can_convert = gdnative_variant_can_convert;
gdni.variant_can_convert_strict = gdnative_variant_can_convert_strict;
- //ptrcalls
-#if 0
- GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type);
- GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type);
-#endif
+ gdni.get_variant_from_type_constructor = gdnative_get_variant_from_type_constructor;
+ gdni.get_variant_to_type_constructor = gdnative_get_type_from_variant_constructor;
+
+ // ptrcalls.
gdni.variant_get_ptr_operator_evaluator = gdnative_variant_get_ptr_operator_evaluator;
gdni.variant_get_ptr_builtin_method = gdnative_variant_get_ptr_builtin_method;
gdni.variant_get_ptr_constructor = gdnative_variant_get_ptr_constructor;
+ gdni.variant_get_ptr_destructor = gdnative_variant_get_ptr_destructor;
gdni.variant_construct = gdnative_variant_construct;
gdni.variant_get_ptr_setter = gdnative_variant_get_ptr_setter;
gdni.variant_get_ptr_getter = gdnative_variant_get_ptr_getter;
@@ -672,6 +835,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.object_destroy = gdnative_object_destroy;
gdni.global_get_singleton = gdnative_global_get_singleton;
gdni.object_get_instance_binding = gdnative_object_get_instance_binding;
+ gdni.object_set_instance_binding = gdnative_object_set_instance_binding;
gdni.object_cast_to = gdnative_object_cast_to;
gdni.object_get_instance_from_id = gdnative_object_get_instance_from_id;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 3e69a28d59..3432d8fabe 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -39,6 +39,11 @@
#include <stdint.h>
#include <stdio.h>
+#ifndef __cplusplus
+typedef uint32_t char32_t;
+typedef uint16_t char16_t;
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -140,12 +145,12 @@ typedef uint64_t GDObjectInstanceID;
/* VARIANT DATA I/O */
typedef enum {
- NATIVE_CALL_OK,
- NATIVE_CALL_ERROR_INVALID_METHOD,
- NATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
- NATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
- NATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
- NATIVE_CALL_ERROR_INSTANCE_IS_NULL,
+ GDNATIVE_CALL_OK,
+ GDNATIVE_CALL_ERROR_INVALID_METHOD,
+ GDNATIVE_CALL_ERROR_INVALID_ARGUMENT, /* expected is variant type */
+ GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS, /* expected is number of arguments */
+ GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS, /* expected is number of arguments */
+ GDNATIVE_CALL_ERROR_INSTANCE_IS_NULL,
} GDNativeCallErrorType;
@@ -160,6 +165,7 @@ typedef void (*GDNativeTypeFromVariantConstructorFunc)(GDNativeTypePtr, GDNative
typedef void (*GDNativePtrOperatorEvaluator)(const GDNativeTypePtr p_left, const GDNativeTypePtr p_right, GDNativeTypePtr r_result);
typedef void (*GDNativePtrBuiltInMethod)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args, GDNativeTypePtr r_return, int p_argument_count);
typedef void (*GDNativePtrConstructor)(GDNativeTypePtr p_base, const GDNativeTypePtr *p_args);
+typedef void (*GDNativePtrDestructor)(GDNativeTypePtr p_base);
typedef void (*GDNativePtrSetter)(GDNativeTypePtr p_base, const GDNativeTypePtr p_value);
typedef void (*GDNativePtrGetter)(const GDNativeTypePtr p_base, GDNativeTypePtr r_value);
typedef void (*GDNativePtrIndexedSetter)(GDNativeTypePtr p_base, GDNativeInt p_index, const GDNativeTypePtr p_value);
@@ -173,7 +179,7 @@ typedef GDNativeObjectPtr (*GDNativeClassConstructor)();
typedef void *(*GDNativeInstanceBindingCreateCallback)(void *p_token, void *p_instance);
typedef void (*GDNativeInstanceBindingFreeCallback)(void *p_token, void *p_instance, void *p_binding);
-typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_instance, GDNativeBool p_reference);
+typedef GDNativeBool (*GDNativeInstanceBindingReferenceCallback)(void *p_token, void *p_binding, GDNativeBool p_reference);
struct GDNativeInstanceBindingCallbacks {
GDNativeInstanceBindingCreateCallback create_callback;
@@ -206,6 +212,7 @@ typedef void (*GDNativeExtensionClassUnreference)(GDExtensionClassInstancePtr p_
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
typedef GDExtensionClassInstancePtr (*GDNativeExtensionClassCreateInstance)(void *p_userdata);
typedef void (*GDNativeExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance);
+typedef void (*GDNativeExtensionClassObjectInstance)(GDExtensionClassInstancePtr p_instance, GDNativeObjectPtr p_object_instance);
typedef GDNativeExtensionClassCallVirtual (*GDNativeExtensionClassGetVirtual)(void *p_userdata, const char *p_name);
typedef struct {
@@ -219,7 +226,8 @@ typedef struct {
GDNativeExtensionClassUnreference unreference_func;
GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
- GDNativeExtensionClassGetVirtual get_firtual_func;
+ GDNativeExtensionClassObjectInstance object_instance_func; /* this one is mandatory */
+ GDNativeExtensionClassGetVirtual get_virtual_func;
void *class_userdata;
} GDNativeExtensionClassCreationInfo;
@@ -256,8 +264,8 @@ typedef enum {
GDNATIVE_EXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
} GDNativeExtensionClassMethodArgumentMetadata;
-typedef void (*GDNativeExtensionClassMethodCall)(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
-typedef void (*GDNativeExtensionClassMethodPtrCall)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
+typedef void (*GDNativeExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeVariantPtr r_return, GDNativeCallError *r_error);
+typedef void (*GDNativeExtensionClassMethodPtrCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
/* passing -1 as argument in the following functions refers to the return type */
typedef GDNativeVariantType (*GDNativeExtensionClassMethodGetArgumentType)(void *p_method_userdata, int32_t p_argument);
@@ -339,6 +347,7 @@ typedef struct {
GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b);
GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash);
GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor);
+ GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type);
void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error);
GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member);
GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member);
@@ -383,7 +392,8 @@ typedef struct {
void (*object_method_bind_ptrcall)(GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret);
void (*object_destroy)(GDNativeObjectPtr p_o);
GDNativeObjectPtr (*global_get_singleton)(const char *p_name);
- void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, GDNativeInstanceBindingCallbacks *p_callbacks);
+ void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag);
GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id);
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 16bc28e0a2..91d304627a 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "native_extension.h"
+#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
@@ -69,7 +70,7 @@ public:
Variant ret;
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
GDNativeCallError ce;
- call_func(extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
+ call_func(method_userdata, extension_instance, (const GDNativeVariantPtr *)p_args, p_arg_count, (GDNativeVariantPtr)&ret, &ce);
r_error.error = Callable::CallError::Error(ce.error);
r_error.argument = ce.argument;
r_error.expected = ce.expected;
@@ -78,7 +79,7 @@ public:
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) {
ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
- ptrcall_func(extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
+ ptrcall_func(method_userdata, extension_instance, (const GDNativeTypePtr *)p_args, (GDNativeTypePtr)r_ret);
}
virtual bool is_vararg() const {
@@ -91,6 +92,7 @@ public:
get_argument_type_func = p_method_info->get_argument_type_func;
get_argument_info_func = p_method_info->get_argument_info_func;
get_argument_metadata_func = p_method_info->get_argument_metadata_func;
+ set_name(p_method_info->name);
vararg = p_method_info->method_flags & GDNATIVE_EXTENSION_METHOD_FLAG_VARARG;
@@ -109,7 +111,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(String(class_name).is_valid_identifier(), "Attempt to register extension clas '" + class_name + "', which is not a valid class identifier.");
+ ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
Extension *parent_extension = nullptr;
@@ -150,6 +152,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
extension->native_extension.unreference = p_extension_funcs->unreference_func;
extension->native_extension.class_userdata = p_extension_funcs->class_userdata;
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
+ extension->native_extension.set_object_instance = p_extension_funcs->object_instance_func;
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
ClassDB::register_extension_class(&extension->native_extension);
@@ -159,11 +162,12 @@ void NativeExtension::_register_extension_class_method(const GDNativeExtensionCl
StringName class_name = p_class_name;
StringName method_name = p_method_info->name;
- ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension method '" + String(method_name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
NativeExtensionMethodBind *method = memnew(NativeExtensionMethodBind(p_method_info));
+ method->set_instance_class(class_name);
ClassDB::bind_method_custom(class_name, method);
}
@@ -171,7 +175,7 @@ void NativeExtension::_register_extension_class_integer_constant(const GDNativeE
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension constant '" + String(p_constant_name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
@@ -181,7 +185,7 @@ void NativeExtension::_register_extension_class_property(const GDNativeExtension
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class property '" + String(p_info->name) + "' for unexisting class '" + class_name + "'.");
//Extension *extension = &self->extension_classes[class_name];
PropertyInfo pinfo;
@@ -199,7 +203,7 @@ void NativeExtension::_register_extension_class_signal(const GDNativeExtensionCl
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to register extension class signal '" + String(p_signal_name) + "' for unexisting class '" + class_name + "'.");
MethodInfo s;
s.name = p_signal_name;
@@ -220,7 +224,7 @@ void NativeExtension::_unregister_extension_class(const GDNativeExtensionClassLi
NativeExtension *self = (NativeExtension *)p_library;
StringName class_name = p_class_name;
- ERR_FAIL_COND_MSG(self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
+ ERR_FAIL_COND_MSG(!self->extension_classes.has(class_name), "Attempt to unregister unexisting extension class '" + class_name + "'.");
Extension *ext = &self->extension_classes[class_name];
ERR_FAIL_COND_MSG(ext->native_extension.children.size(), "Attempt to unregister class '" + class_name + "' while other extension classes inherit from it.");
@@ -368,7 +372,7 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
}
}
- if (library_path != String()) {
+ if (library_path == String()) {
if (r_error) {
*r_error = ERR_FILE_NOT_FOUND;
}
@@ -381,7 +385,8 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
Ref<NativeExtension> lib;
lib.instantiate();
- err = lib->open_library(library_path, entry_symbol);
+ String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
+ err = lib->open_library(abs_path, entry_symbol);
if (r_error) {
*r_error = err;
diff --git a/core/extension/native_extension.h b/core/extension/native_extension.h
index 0a23848eb2..8bd95b2867 100644
--- a/core/extension/native_extension.h
+++ b/core/extension/native_extension.h
@@ -35,8 +35,8 @@
#include "core/io/resource_loader.h"
#include "core/object/ref_counted.h"
-class NativeExtension : public RefCounted {
- GDCLASS(NativeExtension, RefCounted)
+class NativeExtension : public Resource {
+ GDCLASS(NativeExtension, Resource)
void *library = nullptr; // pointer if valid,
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 4a2abffae8..1715fca9e8 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -32,6 +32,7 @@
#include "core/input/input_map.h"
#include "core/os/keyboard.h"
+#include "scene/gui/shortcut.h"
const int InputEvent::DEVICE_ID_TOUCH_MOUSE = -1;
const int InputEvent::DEVICE_ID_INTERNAL = -2;
@@ -1512,3 +1513,26 @@ void InputEventMIDI::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_number"), "set_controller_number", "get_controller_number");
ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_value"), "set_controller_value", "get_controller_value");
}
+
+///////////////////////////////////
+
+void InputEventShortcut::set_shortcut(Ref<Shortcut> p_shortcut) {
+ shortcut = p_shortcut;
+ emit_changed();
+}
+
+Ref<Shortcut> InputEventShortcut::get_shortcut() {
+ return shortcut;
+}
+
+bool InputEventShortcut::is_pressed() const {
+ return true;
+}
+
+String InputEventShortcut::as_text() const {
+ return vformat(RTR("Input Event with Shortcut=%s"), shortcut->get_as_text());
+}
+
+String InputEventShortcut::to_string() {
+ return vformat("InputEventShortcut: shortcut=%s", shortcut->get_as_text());
+}
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 76a45c04a4..98d204fe13 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -42,6 +42,8 @@
* The events are pretty obvious.
*/
+class Shortcut;
+
/**
* Input Modifier Status
* for keyboard/mouse events.
@@ -538,4 +540,18 @@ public:
InputEventMIDI() {}
};
+class InputEventShortcut : public InputEvent {
+ GDCLASS(InputEventShortcut, InputEvent);
+
+ Ref<Shortcut> shortcut;
+
+public:
+ void set_shortcut(Ref<Shortcut> p_shortcut);
+ Ref<Shortcut> get_shortcut();
+ virtual bool is_pressed() const override;
+
+ virtual String as_text() const override;
+ virtual String to_string() override;
+};
+
#endif // INPUT_EVENT_H
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 1c3f231170..f792dc6cb4 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -33,6 +33,7 @@
#include "core/debugger/engine_debugger.h"
#include "core/io/marshalls.h"
#include "scene/main/node.h"
+#include "scene/resources/packed_scene.h"
#include <stdint.h>
@@ -146,6 +147,7 @@ void MultiplayerAPI::poll() {
}
void MultiplayerAPI::clear() {
+ replicated_nodes.clear();
connected_peers.clear();
path_get_cache.clear();
path_send_cache.clear();
@@ -322,6 +324,12 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_
case NETWORK_COMMAND_RAW: {
_process_raw(p_from, p_packet, p_packet_len);
} break;
+ case NETWORK_COMMAND_SPAWN: {
+ _process_spawn_despawn(p_from, p_packet, p_packet_len, true);
+ } break;
+ case NETWORK_COMMAND_DESPAWN: {
+ _process_spawn_despawn(p_from, p_packet, p_packet_len, false);
+ } break;
}
}
@@ -506,6 +514,64 @@ void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet,
E->get() = true;
}
+void MultiplayerAPI::_process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn) {
+ ERR_FAIL_COND_MSG(p_packet_len < 18, "Invalid spawn packet received");
+ int ofs = 1;
+ ResourceUID::ID id = decode_uint64(&p_packet[ofs]);
+ ofs += 8;
+ ERR_FAIL_COND_MSG(!spawnables.has(id), "Invalid spawn ID received " + itos(id));
+
+ uint32_t node_target = decode_uint32(&p_packet[ofs]);
+ Node *parent = _process_get_node(p_from, nullptr, node_target, 0);
+ ofs += 4;
+ ERR_FAIL_COND_MSG(parent == nullptr, "Invalid packet received. Requested node was not found.");
+
+ uint32_t name_len = decode_uint32(&p_packet[ofs]);
+ ofs += 4;
+ ERR_FAIL_COND_MSG(name_len > uint32_t(p_packet_len - ofs), vformat("Invalid spawn packet size: %d, wants: %d", p_packet_len, ofs + name_len));
+ ERR_FAIL_COND_MSG(name_len < 1, "Zero spawn name size.");
+
+ const String name = String::utf8((const char *)&p_packet[ofs], name_len);
+ // We need to make sure no trickery happens here (e.g. despawning a subpath), but we want to allow autogenerated ("@") node names.
+ ERR_FAIL_COND_MSG(name.validate_node_name() != name.replace("@", ""), vformat("Invalid node name received: '%s'", name));
+ ofs += name_len;
+ PackedByteArray data;
+ if (p_packet_len > ofs) {
+ data.resize(p_packet_len - ofs);
+ memcpy(data.ptrw(), &p_packet[ofs], data.size());
+ }
+
+ SpawnMode mode = spawnables[id];
+ if (mode == SPAWN_MODE_SERVER && p_from == 1) {
+ String scene_path = ResourceUID::get_singleton()->get_id_path(id);
+ if (p_spawn) {
+ ERR_FAIL_COND_MSG(parent->has_node(name), vformat("Unable to spawn node. Node already exists: %s/%s", parent->get_path(), name));
+ RES res = ResourceLoader::load(scene_path);
+ ERR_FAIL_COND_MSG(!res.is_valid(), "Unable to load scene to spawn at path: " + scene_path);
+ PackedScene *scene = Object::cast_to<PackedScene>(res.ptr());
+ ERR_FAIL_COND(!scene);
+ Node *node = scene->instantiate();
+ ERR_FAIL_COND(!node);
+ replicated_nodes[node->get_instance_id()] = id;
+ parent->_add_child_nocheck(node, name);
+ emit_signal(SNAME("network_spawn"), p_from, id, node, data);
+ } else {
+ ERR_FAIL_COND_MSG(!parent->has_node(name), vformat("Path not found: %s/%s", parent->get_path(), name));
+ Node *node = parent->get_node(name);
+ ERR_FAIL_COND_MSG(!replicated_nodes.has(node->get_instance_id()), vformat("Trying to despawn a Node that was not replicated: %s/%s", parent->get_path(), name));
+ emit_signal(SNAME("network_despawn"), p_from, id, node, data);
+ replicated_nodes.erase(node->get_instance_id());
+ node->queue_delete();
+ }
+ } else {
+ if (p_spawn) {
+ emit_signal(SNAME("network_spawn_request"), p_from, id, parent, name, data);
+ } else {
+ emit_signal(SNAME("network_despawn_request"), p_from, id, parent, name, data);
+ }
+ }
+}
+
bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentCache *psc, int p_target) {
bool has_all_peers = true;
List<int> peers_to_add; // If one is missing, take note to add it.
@@ -909,6 +975,16 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, uint16_t p_rpc_id, const
void MultiplayerAPI::_add_peer(int p_id) {
connected_peers.insert(p_id);
path_get_cache.insert(p_id, PathGetCache());
+ if (is_network_server()) {
+ for (const KeyValue<ObjectID, ResourceUID::ID> &E : replicated_nodes) {
+ // Only server mode adds to replicated_nodes, no need to check it.
+ Object *obj = ObjectDB::get_instance(E.key);
+ ERR_CONTINUE(!obj);
+ Node *node = Object::cast_to<Node>(obj);
+ ERR_CONTINUE(!node);
+ _send_spawn_despawn(p_id, E.value, node->get_path(), nullptr, 0, true);
+ }
+ }
emit_signal(SNAME("network_peer_connected"), p_id);
}
@@ -924,6 +1000,10 @@ void MultiplayerAPI::_del_peer(int p_id) {
PathSentCache *psc = path_send_cache.getptr(E);
psc->confirmed_peers.erase(p_id);
}
+ if (p_id == 1) {
+ // Erase server replicated nodes, but do not queue them for deletion.
+ replicated_nodes.clear();
+ }
emit_signal(SNAME("network_peer_disconnected"), p_id);
}
@@ -1067,6 +1147,99 @@ bool MultiplayerAPI::is_object_decoding_allowed() const {
return allow_object_decoding;
}
+Error MultiplayerAPI::spawnable_config(const ResourceUID::ID &p_id, SpawnMode p_mode) {
+ ERR_FAIL_COND_V(p_mode < SPAWN_MODE_NONE || p_mode > SPAWN_MODE_CUSTOM, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!ResourceUID::get_singleton()->has_id(p_id), ERR_INVALID_PARAMETER);
+#ifdef TOOLS_ENABLED
+ String path = ResourceUID::get_singleton()->get_id_path(p_id);
+ RES res = ResourceLoader::load(path);
+ ERR_FAIL_COND_V(!res->is_class("PackedScene"), ERR_INVALID_PARAMETER);
+#endif
+ if (p_mode == SPAWN_MODE_NONE) {
+ if (spawnables.has(p_id)) {
+ spawnables.erase(p_id);
+ }
+ } else {
+ spawnables[p_id] = p_mode;
+ }
+ return OK;
+}
+
+Error MultiplayerAPI::send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data) {
+ return _send_spawn_despawn(p_peer_id, p_scene_id, p_path, p_data.ptr(), p_data.size(), false);
+}
+
+Error MultiplayerAPI::send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data) {
+ return _send_spawn_despawn(p_peer_id, p_scene_id, p_path, p_data.ptr(), p_data.size(), true);
+}
+
+Error MultiplayerAPI::_send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const uint8_t *p_data, int p_data_len, bool p_spawn) {
+ ERR_FAIL_COND_V(!root_node, ERR_UNCONFIGURED);
+ ERR_FAIL_COND_V_MSG(!spawnables.has(p_scene_id), ERR_INVALID_PARAMETER, vformat("Spawnable not found: %d", p_scene_id));
+
+ NodePath rel_path = (root_node->get_path()).rel_path_to(p_path);
+ const Vector<StringName> names = rel_path.get_names();
+ ERR_FAIL_COND_V(names.size() < 2, ERR_INVALID_PARAMETER);
+
+ NodePath parent = NodePath(names.subarray(0, names.size() - 2), false);
+ ERR_FAIL_COND_V_MSG(!root_node->has_node(parent), ERR_INVALID_PARAMETER, "Path not found: " + parent);
+
+ // See if the path is cached.
+ PathSentCache *psc = path_send_cache.getptr(parent);
+ if (!psc) {
+ // Path is not cached, create.
+ path_send_cache[parent] = PathSentCache();
+ psc = path_send_cache.getptr(parent);
+ psc->id = last_send_cache_id++;
+ }
+ _send_confirm_path(root_node->get_node(parent), parent, psc, p_peer_id);
+
+ const CharString cname = String(names[names.size() - 1]).utf8();
+ int nlen = encode_cstring(cname.get_data(), nullptr);
+ MAKE_ROOM(1 + 8 + 4 + 4 + nlen + p_data_len);
+ uint8_t *ptr = packet_cache.ptrw();
+ ptr[0] = p_spawn ? NETWORK_COMMAND_SPAWN : NETWORK_COMMAND_DESPAWN;
+ int ofs = 1;
+ ofs += encode_uint64(p_scene_id, &ptr[ofs]);
+ ofs += encode_uint32(psc->id, &ptr[ofs]);
+ ofs += encode_uint32(nlen, &ptr[ofs]);
+ ofs += encode_cstring(cname.get_data(), &ptr[ofs]);
+ memcpy(&ptr[ofs], p_data, p_data_len);
+ network_peer->set_target_peer(p_peer_id);
+ network_peer->set_transfer_channel(0);
+ network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
+ return network_peer->put_packet(ptr, ofs + p_data_len);
+}
+
+void MultiplayerAPI::scene_enter_exit_notify(const String &p_scene, const Node *p_node, bool p_enter) {
+ if (!has_network_peer()) {
+ return;
+ }
+ ERR_FAIL_COND(!p_node || !p_node->get_parent() || !root_node);
+ NodePath path = (root_node->get_path()).rel_path_to(p_node->get_parent()->get_path());
+ if (path.is_empty()) {
+ return;
+ }
+ ResourceUID::ID id = ResourceLoader::get_resource_uid(p_scene);
+ if (!spawnables.has(id)) {
+ return;
+ }
+ SpawnMode mode = spawnables[id];
+ if (p_enter) {
+ if (mode == SPAWN_MODE_SERVER && is_network_server()) {
+ replicated_nodes[p_node->get_instance_id()] = id;
+ _send_spawn_despawn(0, id, p_node->get_path(), nullptr, 0, true);
+ }
+ emit_signal(SNAME("network_spawnable_added"), id, p_node);
+ } else {
+ if (mode == SPAWN_MODE_SERVER && is_network_server() && replicated_nodes.has(p_node->get_instance_id())) {
+ replicated_nodes.erase(p_node->get_instance_id());
+ _send_spawn_despawn(0, id, p_node->get_path(), nullptr, 0, false);
+ }
+ emit_signal(SNAME("network_spawnable_removed"), id, p_node);
+ }
+}
+
void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node);
ClassDB::bind_method(D_METHOD("get_root_node"), &MultiplayerAPI::get_root_node);
@@ -1085,6 +1258,9 @@ void MultiplayerAPI::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &MultiplayerAPI::is_refusing_new_network_connections);
ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &MultiplayerAPI::set_allow_object_decoding);
ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &MultiplayerAPI::is_object_decoding_allowed);
+ ClassDB::bind_method(D_METHOD("spawnable_config", "scene_id", "spawn_mode"), &MultiplayerAPI::spawnable_config);
+ ClassDB::bind_method(D_METHOD("send_despawn", "peer_id", "scene_id", "path", "data"), &MultiplayerAPI::send_despawn, DEFVAL(PackedByteArray()));
+ ClassDB::bind_method(D_METHOD("send_spawn", "peer_id", "scene_id", "path", "data"), &MultiplayerAPI::send_spawn, DEFVAL(PackedByteArray()));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
@@ -1098,11 +1274,21 @@ void MultiplayerAPI::_bind_methods() {
ADD_SIGNAL(MethodInfo("connected_to_server"));
ADD_SIGNAL(MethodInfo("connection_failed"));
ADD_SIGNAL(MethodInfo("server_disconnected"));
+ ADD_SIGNAL(MethodInfo("network_despawn", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("network_spawn", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("network_despawn_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("network_spawn_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "parent", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data")));
+ ADD_SIGNAL(MethodInfo("network_spawnable_added", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("network_spawnable_removed", PropertyInfo(Variant::INT, "scene_id"), PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
BIND_ENUM_CONSTANT(RPC_MODE_MASTER);
BIND_ENUM_CONSTANT(RPC_MODE_PUPPET);
+
+ BIND_ENUM_CONSTANT(SPAWN_MODE_NONE);
+ BIND_ENUM_CONSTANT(SPAWN_MODE_SERVER);
+ BIND_ENUM_CONSTANT(SPAWN_MODE_CUSTOM);
}
MultiplayerAPI::MultiplayerAPI() {
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index 011bc3dde9..9552a0bf35 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -32,6 +32,7 @@
#define MULTIPLAYER_API_H
#include "core/io/multiplayer_peer.h"
+#include "core/io/resource_uid.h"
#include "core/object/ref_counted.h"
class MultiplayerAPI : public RefCounted {
@@ -45,6 +46,12 @@ public:
RPC_MODE_PUPPET, // Using rpc() on it will call method for all puppets
};
+ enum SpawnMode {
+ SPAWN_MODE_NONE,
+ SPAWN_MODE_SERVER,
+ SPAWN_MODE_CUSTOM,
+ };
+
struct RPCConfig {
StringName name;
RPCMode rpc_mode = RPC_MODE_DISABLED;
@@ -82,10 +89,12 @@ private:
};
Ref<MultiplayerPeer> network_peer;
+ Map<ResourceUID::ID, SpawnMode> spawnables;
int rpc_sender_id = 0;
Set<int> connected_peers;
HashMap<NodePath, PathSentCache> path_send_cache;
Map<int, PathGetCache> path_get_cache;
+ Map<ObjectID, ResourceUID::ID> replicated_nodes;
int last_send_cache_id;
Vector<uint8_t> packet_cache;
Node *root_node = nullptr;
@@ -97,6 +106,7 @@ protected:
void _process_packet(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len);
void _process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len);
+ void _process_spawn_despawn(int p_from, const uint8_t *p_packet, int p_packet_len, bool p_spawn);
Node *_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len);
void _process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset);
void _process_raw(int p_from, const uint8_t *p_packet, int p_packet_len);
@@ -113,6 +123,8 @@ public:
NETWORK_COMMAND_SIMPLIFY_PATH,
NETWORK_COMMAND_CONFIRM_PATH,
NETWORK_COMMAND_RAW,
+ NETWORK_COMMAND_SPAWN,
+ NETWORK_COMMAND_DESPAWN,
};
enum NetworkNodeIdCompression {
@@ -154,10 +166,17 @@ public:
void set_allow_object_decoding(bool p_enable);
bool is_object_decoding_allowed() const;
+ Error spawnable_config(const ResourceUID::ID &p_id, SpawnMode p_mode);
+ Error send_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data = PackedByteArray());
+ Error send_spawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const PackedByteArray &p_data = PackedByteArray());
+ Error _send_spawn_despawn(int p_peer_id, const ResourceUID::ID &p_scene_id, const NodePath &p_path, const uint8_t *p_data, int p_data_len, bool p_spawn);
+ void scene_enter_exit_notify(const String &p_scene, const Node *p_node, bool p_enter);
+
MultiplayerAPI();
~MultiplayerAPI();
};
VARIANT_ENUM_CAST(MultiplayerAPI::RPCMode);
+VARIANT_ENUM_CAST(MultiplayerAPI::SpawnMode);
#endif // MULTIPLAYER_API_H
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index aa3831d4cf..b5e25fb837 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -1129,3 +1129,21 @@ void Basis::rotate_sh(real_t *p_values) {
p_values[7] = -d3;
p_values[8] = d4 * s_scale_dst4;
}
+
+Basis Basis::looking_at(const Vector3 &p_target, const Vector3 &p_up) {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(p_target.is_equal_approx(Vector3()), Basis(), "The target vector can't be zero.");
+ ERR_FAIL_COND_V_MSG(p_up.is_equal_approx(Vector3()), Basis(), "The up vector can't be zero.");
+#endif
+ Vector3 v_z = -p_target.normalized();
+ Vector3 v_x = p_up.cross(v_z);
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V_MSG(v_x.is_equal_approx(Vector3()), Basis(), "The target vector and up vector can't be parallel to each other.");
+#endif
+ v_x.normalize();
+ Vector3 v_y = v_z.cross(v_x);
+
+ Basis basis;
+ basis.set(v_x, v_y, v_z);
+ return basis;
+}
diff --git a/core/math/basis.h b/core/math/basis.h
index 2889a4aa5e..3db2227b70 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -242,6 +242,8 @@ public:
operator Quaternion() const { return get_quaternion(); }
+ static Basis looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
+
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); };
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index 7692e1be47..c3a8f910c0 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -81,6 +81,26 @@ enum VAlign {
VALIGN_BOTTOM
};
+enum InlineAlign {
+ // Image alignment points.
+ INLINE_ALIGN_TOP_TO = 0b0000,
+ INLINE_ALIGN_CENTER_TO = 0b0001,
+ INLINE_ALIGN_BOTTOM_TO = 0b0010,
+ INLINE_ALIGN_IMAGE_MASK = 0b0011,
+
+ // Text alignment points.
+ INLINE_ALIGN_TO_TOP = 0b0000,
+ INLINE_ALIGN_TO_CENTER = 0b0100,
+ INLINE_ALIGN_TO_BASELINE = 0b1000,
+ INLINE_ALIGN_TO_BOTTOM = 0b1100,
+ INLINE_ALIGN_TEXT_MASK = 0b1100,
+
+ // Presets.
+ INLINE_ALIGN_TOP = INLINE_ALIGN_TOP_TO | INLINE_ALIGN_TO_TOP,
+ INLINE_ALIGN_CENTER = INLINE_ALIGN_CENTER_TO | INLINE_ALIGN_TO_CENTER,
+ INLINE_ALIGN_BOTTOM = INLINE_ALIGN_BOTTOM_TO | INLINE_ALIGN_TO_BOTTOM
+};
+
enum Side {
SIDE_LEFT,
SIDE_TOP,
diff --git a/core/math/transform_3d.cpp b/core/math/transform_3d.cpp
index 51766b39f4..4f4943c8ef 100644
--- a/core/math/transform_3d.cpp
+++ b/core/math/transform_3d.cpp
@@ -71,40 +71,12 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_phi) {
Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const {
Transform3D t = *this;
- t.set_look_at(origin, p_target, p_up);
+ t.basis = Basis::looking_at(p_target - origin, p_up);
return t;
}
void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) {
-#ifdef MATH_CHECKS
- ERR_FAIL_COND(p_eye == p_target);
- ERR_FAIL_COND(p_up.length() == 0);
-#endif
- // Reference: MESA source code
- Vector3 v_x, v_y, v_z;
-
- /* Make rotation matrix */
-
- /* Z vector */
- v_z = p_eye - p_target;
-
- v_z.normalize();
-
- v_y = p_up;
-
- v_x = v_y.cross(v_z);
-#ifdef MATH_CHECKS
- ERR_FAIL_COND(v_x.length() == 0);
-#endif
-
- /* Recompute Y = Z cross X */
- v_y = v_z.cross(v_x);
-
- v_x.normalize();
- v_y.normalize();
-
- basis.set(v_x, v_y, v_z);
-
+ basis = Basis::looking_at(p_target - p_eye, p_up);
origin = p_eye;
}
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index c6ba39be94..c58fe7bc24 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -505,11 +505,12 @@ thread_local bool initializing_with_extension = false;
thread_local ObjectNativeExtension *initializing_extension = nullptr;
thread_local GDExtensionClassInstancePtr initializing_extension_instance = nullptr;
-void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance) {
+void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance, Object *p_base) {
if (initializing_with_extension) {
*r_extension = initializing_extension;
*r_extension_instance = initializing_extension_instance;
initializing_with_extension = false;
+ initializing_extension->set_object_instance(*r_extension_instance, p_base);
} else {
*r_extension = nullptr;
*r_extension_instance = nullptr;
@@ -1592,7 +1593,7 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
GLOBAL_LOCK_FUNCTION;
ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
- ERR_FAIL_COND_MSG(classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
+ ERR_FAIL_COND_MSG(!classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
@@ -1604,6 +1605,7 @@ void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
c.inherits = parent->name;
c.class_ptr = parent->class_ptr;
c.inherits_ptr = parent;
+ c.exposed = true;
classes[p_extension->class_name] = c;
}
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 3a84e9ab38..bfc9d6f283 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -233,7 +233,7 @@ public:
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
- static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance);
+ static void instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance, Object *p_base);
static APIType get_api_type(const StringName &p_class);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index d552d5e5e0..c191109a8f 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1815,7 +1815,7 @@ void Object::_construct_object(bool p_reference) {
type_is_reference = p_reference;
_instance_id = ObjectDB::add_instance(this);
- ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance);
+ ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance, this);
#ifdef DEBUG_ENABLED
_lock_index.init(1);
@@ -1876,7 +1876,7 @@ Object::~Object() {
if (_instance_bindings != nullptr) {
for (uint32_t i = 0; i < _instance_binding_count; i++) {
if (_instance_bindings[i].free_callback) {
- _instance_bindings[i].free_callback(_instance_bindings[i].token, _instance_bindings[i].binding, this);
+ _instance_bindings[i].free_callback(_instance_bindings[i].token, this, _instance_bindings[i].binding);
}
}
memfree(_instance_bindings);
diff --git a/core/object/object.h b/core/object/object.h
index b7d0916a54..1f5e17c99f 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -272,6 +272,7 @@ struct ObjectNativeExtension {
GDNativeExtensionClassCreateInstance create_instance;
GDNativeExtensionClassFreeInstance free_instance;
+ GDNativeExtensionClassObjectInstance set_object_instance;
GDNativeExtensionClassGetVirtual get_virtual;
};
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 3d1cb4a8e1..f801be3db3 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -82,6 +82,7 @@ static Ref<ResourceFormatLoaderImage> resource_format_image;
static Ref<TranslationLoaderPO> resource_format_po;
static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto;
static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto;
+static Ref<NativeExtensionResourceLoader> resource_loader_native_extension;
static _ResourceLoader *_resource_loader = nullptr;
static _ResourceSaver *_resource_saver = nullptr;
@@ -234,6 +235,9 @@ void register_core_types() {
native_extension_manager = memnew(NativeExtensionManager);
+ resource_loader_native_extension.instantiate();
+ ResourceLoader::add_resource_format_loader(resource_loader_native_extension);
+
ip = IP::create();
_geometry_2d = memnew(_Geometry2D);
@@ -298,6 +302,7 @@ void register_core_singletons() {
void register_core_extensions() {
// Hardcoded for now.
+ NativeExtension::initialize_native_extensions();
if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
for (int i = 0; i < paths.size(); i++) {
@@ -349,6 +354,9 @@ void unregister_core_types() {
memdelete(ip);
}
+ ResourceLoader::remove_resource_format_loader(resource_loader_native_extension);
+ resource_loader_native_extension.unref();
+
ResourceLoader::finalize();
ClassDB::cleanup_defaults();
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 3cb2a6bfb5..001da3ddcb 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -101,6 +101,7 @@ VARIANT_ENUM_CAST(MouseButton);
VARIANT_ENUM_CAST(Orientation);
VARIANT_ENUM_CAST(HAlign);
VARIANT_ENUM_CAST(VAlign);
+VARIANT_ENUM_CAST(InlineAlign);
VARIANT_ENUM_CAST(PropertyHint);
VARIANT_ENUM_CAST(PropertyUsageFlags);
VARIANT_ENUM_CAST(Variant::Type);
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 97a1b4c02a..d538b9faff 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3533,12 +3533,13 @@ void Variant::register_types() {
_register_variant_methods();
_register_variant_setters_getters();
_register_variant_constructors();
+ _register_variant_destructors();
_register_variant_utility_functions();
}
void Variant::unregister_types() {
_unregister_variant_operators();
_unregister_variant_methods();
_unregister_variant_setters_getters();
- _unregister_variant_constructors();
+ _unregister_variant_destructors();
_unregister_variant_utility_functions();
}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 780f9b4e70..9ec131a1b8 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -208,7 +208,7 @@ private:
Transform3D *_transform3d;
PackedArrayRefBase *packed_array;
void *_ptr; //generic pointer
- uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
+ uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 };
} _data alignas(8);
void reference(const Variant &p_variant);
@@ -271,6 +271,8 @@ private:
static void _register_variant_setters_getters();
static void _unregister_variant_setters_getters();
static void _register_variant_constructors();
+ static void _unregister_variant_destructors();
+ static void _register_variant_destructors();
static void _unregister_variant_constructors();
static void _register_variant_utility_functions();
static void _unregister_variant_utility_functions();
@@ -534,6 +536,14 @@ public:
static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience
+ /* Destructors */
+
+ // Only ptrcall is available.
+ typedef void (*PTRDestructor)(void *base);
+
+ static PTRDestructor get_ptr_destructor(Variant::Type p_type);
+ static bool has_destructor(Variant::Type p_type);
+
/* Properties */
void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid);
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index f8538f71d3..c3481d4896 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1709,7 +1709,7 @@ static void _register_variant_builtin_methods() {
bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray());
bind_method(Transform2D, is_equal_approx, sarray("xform"), varray());
bind_method(Transform2D, set_rotation, sarray("rotation"), varray());
- bind_method(Transform2D, looking_at, sarray("target"), varray(Transform2D()));
+ bind_method(Transform2D, looking_at, sarray("target"), varray(Vector2()));
/* Basis */
@@ -1728,6 +1728,7 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, slerp, sarray("to", "weight"), varray());
bind_method(Basis, is_equal_approx, sarray("b"), varray());
bind_method(Basis, get_rotation_quaternion, sarray(), varray());
+ bind_static_method(Basis, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
/* AABB */
diff --git a/core/variant/variant_destruct.cpp b/core/variant/variant_destruct.cpp
new file mode 100644
index 0000000000..366b71df3a
--- /dev/null
+++ b/core/variant/variant_destruct.cpp
@@ -0,0 +1,78 @@
+/*************************************************************************/
+/* variant_destruct.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "variant_destruct.h"
+
+#include "core/templates/local_vector.h"
+
+static Variant::PTRDestructor destruct_pointers[Variant::VARIANT_MAX] = { nullptr };
+
+template <class T>
+static void add_destructor() {
+ destruct_pointers[T::get_base_type()] = T::ptr_destruct;
+}
+
+void Variant::_register_variant_destructors() {
+ add_destructor<VariantDestruct<String>>();
+ add_destructor<VariantDestruct<Transform2D>>();
+ add_destructor<VariantDestruct<::AABB>>();
+ add_destructor<VariantDestruct<Basis>>();
+ add_destructor<VariantDestruct<Transform3D>>();
+ add_destructor<VariantDestruct<StringName>>();
+ add_destructor<VariantDestruct<NodePath>>();
+ add_destructor<VariantDestruct<::RID>>();
+ add_destructor<VariantDestruct<Callable>>();
+ add_destructor<VariantDestruct<Signal>>();
+ add_destructor<VariantDestruct<Dictionary>>();
+ add_destructor<VariantDestruct<Array>>();
+ add_destructor<VariantDestruct<PackedByteArray>>();
+ add_destructor<VariantDestruct<PackedInt32Array>>();
+ add_destructor<VariantDestruct<PackedInt64Array>>();
+ add_destructor<VariantDestruct<PackedFloat32Array>>();
+ add_destructor<VariantDestruct<PackedFloat64Array>>();
+ add_destructor<VariantDestruct<PackedStringArray>>();
+ add_destructor<VariantDestruct<PackedVector2Array>>();
+ add_destructor<VariantDestruct<PackedVector3Array>>();
+ add_destructor<VariantDestruct<PackedColorArray>>();
+}
+
+void Variant::_unregister_variant_destructors() {
+ // Nothing to be done.
+}
+
+Variant::PTRDestructor Variant::get_ptr_destructor(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+ return destruct_pointers[p_type];
+}
+
+bool Variant::has_destructor(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ return destruct_pointers[p_type] != nullptr;
+}
diff --git a/core/variant/variant_destruct.h b/core/variant/variant_destruct.h
new file mode 100644
index 0000000000..7356e42201
--- /dev/null
+++ b/core/variant/variant_destruct.h
@@ -0,0 +1,76 @@
+/*************************************************************************/
+/* variant_destruct.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 VARIANT_DESTRUCT_H
+#define VARIANT_DESTRUCT_H
+
+#include "core/variant/variant.h"
+
+#include "core/object/class_db.h"
+
+template <class T>
+struct VariantDestruct {};
+
+#define MAKE_PTRDESTRUCT(m_type) \
+ template <> \
+ struct VariantDestruct<m_type> { \
+ _FORCE_INLINE_ static void ptr_destruct(void *p_ptr) { \
+ reinterpret_cast<m_type *>(p_ptr)->~m_type(); \
+ } \
+ _FORCE_INLINE_ static Variant::Type get_base_type() { \
+ return GetTypeInfo<m_type>::VARIANT_TYPE; \
+ } \
+ }
+
+MAKE_PTRDESTRUCT(String);
+MAKE_PTRDESTRUCT(Transform2D);
+MAKE_PTRDESTRUCT(AABB);
+MAKE_PTRDESTRUCT(Basis);
+MAKE_PTRDESTRUCT(Transform3D);
+MAKE_PTRDESTRUCT(StringName);
+MAKE_PTRDESTRUCT(NodePath);
+MAKE_PTRDESTRUCT(RID);
+MAKE_PTRDESTRUCT(Callable);
+MAKE_PTRDESTRUCT(Signal);
+MAKE_PTRDESTRUCT(Dictionary);
+MAKE_PTRDESTRUCT(Array);
+MAKE_PTRDESTRUCT(PackedByteArray);
+MAKE_PTRDESTRUCT(PackedInt32Array);
+MAKE_PTRDESTRUCT(PackedInt64Array);
+MAKE_PTRDESTRUCT(PackedFloat32Array);
+MAKE_PTRDESTRUCT(PackedFloat64Array);
+MAKE_PTRDESTRUCT(PackedStringArray);
+MAKE_PTRDESTRUCT(PackedVector2Array);
+MAKE_PTRDESTRUCT(PackedVector3Array);
+MAKE_PTRDESTRUCT(PackedColorArray);
+
+#undef MAKE_PTRDESTRUCT
+
+#endif // VARIANT_DESTRUCT_H
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 78e1ad06ae..566b14736e 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -1171,6 +1171,11 @@ struct VariantInitializer<PackedColorArray> {
static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_color_array(v); }
};
+template <>
+struct VariantInitializer<Object *> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::object_assign_null(v); }
+};
+
template <class T>
struct VariantZeroAssigner {
};
@@ -1385,4 +1390,19 @@ struct VariantTypeAdjust<Object *> {
}
};
+// GDNative extension helpers.
+
+template <class T>
+struct VariantTypeConstructor {
+ _FORCE_INLINE_ static void variant_from_type(void *p_variant, void *p_value) {
+ Variant *variant = reinterpret_cast<Variant *>(p_variant);
+ VariantInitializer<T>::init(variant);
+ VariantInternalAccessor<T>::set(variant, *((T *)p_value));
+ }
+
+ _FORCE_INLINE_ static void type_from_variant(void *p_value, void *p_variant) {
+ *((T *)p_value) = VariantInternalAccessor<T>::get(reinterpret_cast<Variant *>(p_variant));
+ }
+};
+
#endif // VARIANT_INTERNAL_H
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index c86812742c..e78c3d97ae 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1128,6 +1128,36 @@
<constant name="VALIGN_BOTTOM" value="2" enum="VAlign">
Vertical bottom alignment, usually for text-derived classes.
</constant>
+ <constant name="INLINE_ALIGN_TOP_TO" value="0" enum="InlineAlign">
+ Aligns the top of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGN_TO_*[/code] constant.
+ </constant>
+ <constant name="INLINE_ALIGN_CENTER_TO" value="1" enum="InlineAlign">
+ Aligns the center of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGN_TO_*[/code] constant.
+ </constant>
+ <constant name="INLINE_ALIGN_BOTTOM_TO" value="2" enum="InlineAlign">
+ Aligns the bottom of the inline object (e.g. image, table) to the position of the text specified by [code]INLINE_ALIGN_TO_*[/code] constant.
+ </constant>
+ <constant name="INLINE_ALIGN_TO_TOP" value="0" enum="InlineAlign">
+ Aligns the position of the inline object (e.g. image, table) specified by [code]INLINE_ALIGN_*_TO[/code] constant to the top of the text.
+ </constant>
+ <constant name="INLINE_ALIGN_TO_CENTER" value="4" enum="InlineAlign">
+ Aligns the position of the inline object (e.g. image, table) specified by [code]INLINE_ALIGN_*_TO[/code] constant to the center of the text.
+ </constant>
+ <constant name="INLINE_ALIGN_TO_BASELINE" value="8" enum="InlineAlign">
+ Aligns the position of the inline object (e.g. image, table) specified by [code]INLINE_ALIGN_*_TO[/code] constant to the baseline of the text.
+ </constant>
+ <constant name="INLINE_ALIGN_TO_BOTTOM" value="12" enum="InlineAlign">
+ Aligns inline object (e.g. image, table) to the bottom of the text.
+ </constant>
+ <constant name="INLINE_ALIGN_TOP" value="0" enum="InlineAlign">
+ Aligns top of the inline object (e.g. image, table) to the top of the text. Equvalent to [code]INLINE_ALIGN_TOP_TO | INLINE_ALIGN_TO_TOP[/code].
+ </constant>
+ <constant name="INLINE_ALIGN_CENTER" value="5" enum="InlineAlign">
+ Aligns center of the inline object (e.g. image, table) to the center of the text. Equvalent to [code]INLINE_ALIGN_CENTER_TO | INLINE_ALIGN_TO_CENTER[/code].
+ </constant>
+ <constant name="INLINE_ALIGN_BOTTOM" value="14" enum="InlineAlign">
+ Aligns bottom of the inline object (e.g. image, table) to the bottom of the text. Equvalent to [code]INLINE_ALIGN_BOTTOM_TO | INLINE_ALIGN_TO_BOTTOM[/code].
+ </constant>
<constant name="SPKEY" value="16777216">
Keycodes with this bit applied are non-printable.
</constant>
@@ -2276,6 +2306,8 @@
<constant name="PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS" value="23" enum="PropertyHint">
Hints that an image is compressed using lossless compression.
</constant>
+ <constant name="PROPERTY_HINT_OBJECT_ID" value="24" enum="PropertyHint">
+ </constant>
<constant name="PROPERTY_HINT_TYPE_STRING" value="25" enum="PropertyHint">
Hint that a property represents a particular type. If a property is [constant TYPE_STRING], allows to set a type from the create dialog. If you need to create an [Array] to contain elements of a specific type, the [code]hint_string[/code] must encode nested types using [code]":"[/code] and [code]"/"[/code] for specifying [Resource] types. For instance:
[codeblock]
@@ -2286,6 +2318,38 @@
[/codeblock]
[b]Note:[/b] the final colon is required to specify for properly detecting built-in types.
</constant>
+ <constant name="PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE" value="26" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_METHOD_OF_VARIANT_TYPE" value="27" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_METHOD_OF_BASE_TYPE" value="28" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_METHOD_OF_INSTANCE" value="29" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_METHOD_OF_SCRIPT" value="30" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE" value="31" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_PROPERTY_OF_BASE_TYPE" value="32" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_PROPERTY_OF_INSTANCE" value="33" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_PROPERTY_OF_SCRIPT" value="34" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_OBJECT_TOO_BIG" value="35" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_NODE_PATH_VALID_TYPES" value="36" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_SAVE_FILE" value="37" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="38" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_HINT_MAX" value="40" enum="PropertyHint">
+ </constant>
+ <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
+ </constant>
<constant name="PROPERTY_USAGE_STORAGE" value="1" enum="PropertyUsageFlags">
The property is serialized and saved in the scene file (default).
</constant>
@@ -2325,6 +2389,36 @@
<constant name="PROPERTY_USAGE_SCRIPT_VARIABLE" value="8192" enum="PropertyUsageFlags">
The property is a script variable which should be serialized and saved in the scene file.
</constant>
+ <constant name="PROPERTY_USAGE_STORE_IF_NULL" value="16384" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_ANIMATE_AS_TRIGGER" value="32768" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED" value="65536" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE" value="131072" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_CLASS_IS_ENUM" value="262144" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_NIL_IS_VARIANT" value="524288" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_INTERNAL" value="1048576" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE" value="2097152" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_HIGH_END_GFX" value="4194304" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT" value="8388608" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT" value="16777216" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_KEYING_INCREMENTS" value="33554432" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_DEFERRED_SET_RESOURCE" value="67108864" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT" value="134217728" enum="PropertyUsageFlags">
+ </constant>
+ <constant name="PROPERTY_USAGE_EDITOR_BASIC_SETTING" value="268435456" enum="PropertyUsageFlags">
+ </constant>
<constant name="PROPERTY_USAGE_DEFAULT" value="7" enum="PropertyUsageFlags">
Default usage (storage, editor and network).
</constant>
diff --git a/doc/classes/Basis.xml b/doc/classes/Basis.xml
index 9a4dd15c63..8fab84d885 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -109,6 +109,15 @@
Returns [code]true[/code] if this basis and [code]b[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
</description>
</method>
+ <method name="looking_at" qualifiers="static">
+ <return type="Basis" />
+ <argument index="0" name="target" type="Vector3" />
+ <argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
+ <description>
+ Creates a Basis with a rotation such that the forward axis (-Z) points towards the [code]target[/code] position.
+ The up axis (+Y) points as close to the [code]up[/code] vector as possible while staying perpendicular to the forward axis. The resulting Basis is orthonormalized. The [code]target[/code] and [code]up[/code] vectors cannot be zero, and cannot be parallel to each other.
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool" />
<argument index="0" name="right" type="Basis" />
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index 1ace7ee6bf..a6138ee7df 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -21,10 +21,10 @@
Returns the surface normal of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
</description>
</method>
- <method name="get_floor_velocity" qualifiers="const">
+ <method name="get_platform_velocity" qualifiers="const">
<return type="Vector2" />
<description>
- Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code].
+ Returns the linear velocity of the platform at the last collision point. Only valid after calling [method move_and_slide].
</description>
</method>
<method name="get_slide_collision">
@@ -61,24 +61,43 @@
Returns [code]true[/code] if the body collided with the ceiling on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
</description>
</method>
+ <method name="is_on_ceiling_only" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the body collided only with the ceiling on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
<method name="is_on_floor" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the body collided with the floor on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
</description>
</method>
+ <method name="is_on_floor_only" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the body collided only with the floor on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
<method name="is_on_wall" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the body collided with a wall on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
</description>
</method>
+ <method name="is_on_wall_only" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the body collided only with a wall on the last call of [method move_and_slide]. Otherwise, returns [code]false[/code].
+ </description>
+ </method>
<method name="move_and_slide">
<return type="void" />
<description>
Moves the body based on [member linear_velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
Modifies [member linear_velocity] if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
+ When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions.
</description>
</method>
</methods>
@@ -89,9 +108,20 @@
A higher value means it's more flexible for detecting collision, which helps with consistently detecting walls and floors.
A lower value forces the collision algorithm to use more exact detection, so it can be used in cases that specifically require precision, e.g at very low scale to avoid visible jittering, or for stability with a stack of character bodies.
</member>
+ <member name="constant_speed_on_floor" type="bool" setter="set_constant_speed_on_floor_enabled" getter="is_constant_speed_on_floor_enabled" default="false">
+ If [code]false[/code] (by default), the body will move faster on downward slopes and slower on upward slopes.
+ If [code]true[/code], the body will always move at the same speed on the ground no matter the slope. Note that you need to use [member floor_snap_length] to stick along a downward slope at constant speed.
+ </member>
+ <member name="exclude_body_layers" type="int" setter="set_exclude_body_layers" getter="get_exclude_body_layers" default="0">
+ Collision layers that will be excluded for detecting bodies that will act as moving platforms to be followed by the [CharacterBody2D]. By default, all touching bodies are detected and propagate their velocity. You can add excluded layers to ignore bodies that are contained in these layers.
+ </member>
<member name="floor_max_angle" type="float" setter="set_floor_max_angle" getter="get_floor_max_angle" default="0.785398">
Maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. The default value equals 45 degrees.
</member>
+ <member name="floor_snap_length" type="float" setter="set_floor_snap_length" getter="get_floor_snap_length" default="0.0">
+ Sets a snapping distance. When set to a value different from [code]0.0[/code], the body is kept attached to slopes when calling [method move_and_slide]. The snapping vector is determined by the given distance along the opposite direction of the [member up_direction].
+ As long as the snapping vector is in contact with the ground and the body moves against `up_direction`, the body will remain attached to the surface. Snapping is not applied if the body moves along `up_direction`, so it will be able to detach from the ground when jumping.
+ </member>
<member name="infinite_inertia" type="bool" setter="set_infinite_inertia_enabled" getter="is_infinite_inertia_enabled" default="true">
If [code]true[/code], the body will be able to push [RigidBody2D] nodes when calling [method move_and_slide], but it also won't detect any collisions with them. If [code]false[/code], it will interact with [RigidBody2D] nodes like with [StaticBody2D].
</member>
@@ -101,9 +131,11 @@
<member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4">
Maximum number of times the body can change direction before it stops when calling [method move_and_slide].
</member>
- <member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0, 0)">
- When set to a value different from [code]Vector2(0, 0)[/code], the body is kept attached to slopes when calling [method move_and_slide].
- As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code]Vector2(0, 0)[/code].
+ <member name="move_on_floor_only" type="bool" setter="set_move_on_floor_only_enabled" getter="is_move_on_floor_only_enabled" default="true">
+ If [code]true[/code], the body will be able to move on the floor only, this option avoids to be able to walk on walls, it will however allow to slide down along them.
+ </member>
+ <member name="slide_on_ceiling" type="bool" setter="set_slide_on_ceiling_enabled" getter="is_slide_on_ceiling_enabled" default="true">
+ If [code]true[/code], during a jump against the ceiling, the body will slide, if [code]false[/code] it will be stopped and will fall vertically.
</member>
<member name="stop_on_slope" type="bool" setter="set_stop_on_slope_enabled" getter="is_stop_on_slope_enabled" default="false">
If [code]true[/code], the body will not slide on slopes when you include gravity in [code]linear_velocity[/code] when calling [method move_and_slide] and the body is standing still.
diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
index 577ab5e84c..4cb4f9a850 100644
--- a/doc/classes/CharacterBody3D.xml
+++ b/doc/classes/CharacterBody3D.xml
@@ -65,6 +65,7 @@
Moves the body based on [member linear_velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
Modifies [member linear_velocity] if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
+ When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions.
</description>
</method>
</methods>
diff --git a/doc/classes/EditorCommandPalette.xml b/doc/classes/EditorCommandPalette.xml
new file mode 100644
index 0000000000..743c59eec2
--- /dev/null
+++ b/doc/classes/EditorCommandPalette.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorCommandPalette" inherits="ConfirmationDialog" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_command">
+ <return type="void" />
+ <argument index="0" name="command_name" type="String" />
+ <argument index="1" name="key_name" type="String" />
+ <argument index="2" name="binded_callable" type="Callable" />
+ <argument index="3" name="shortcut_text" type="String" default="&quot;None&quot;" />
+ <description>
+ </description>
+ </method>
+ <method name="remove_command">
+ <return type="void" />
+ <argument index="0" name="key_name" type="String" />
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" override="true" default="false" />
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml
index 185b4f8c39..91e1dfbf57 100644
--- a/doc/classes/EditorInterface.xml
+++ b/doc/classes/EditorInterface.xml
@@ -30,6 +30,11 @@
Returns the main container of Godot editor's window. For example, you can use it to retrieve the size of the container and place your controls accordingly.
</description>
</method>
+ <method name="get_command_palette" qualifiers="const">
+ <return type="EditorCommandPalette" />
+ <description>
+ </description>
+ </method>
<method name="get_current_path" qualifiers="const">
<return type="String" />
<description>
diff --git a/doc/classes/MultiplayerAPI.xml b/doc/classes/MultiplayerAPI.xml
index 552e0fce4c..b9f50ad02a 100644
--- a/doc/classes/MultiplayerAPI.xml
+++ b/doc/classes/MultiplayerAPI.xml
@@ -66,6 +66,34 @@
Sends the given raw [code]bytes[/code] to a specific peer identified by [code]id[/code] (see [method MultiplayerPeer.set_target_peer]). Default ID is [code]0[/code], i.e. broadcast to all peers.
</description>
</method>
+ <method name="send_despawn">
+ <return type="int" enum="Error" />
+ <argument index="0" name="peer_id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="path" type="NodePath" />
+ <argument index="3" name="data" type="PackedByteArray" default="PackedByteArray()" />
+ <description>
+ Sends a despawn request for the scene identified by [code]scene_id[/code] to the given [code]peer_id[/code] (see [method MultiplayerPeer.set_target_peer]). If the scene is configured as [constant SPAWN_MODE_SERVER] (see [method spawnable_config]) and the request is sent by the server (see [method is_network_server]), the receiving peer(s) will automatically queue for deletion the node at [code]path[/code] and emit the signal [signal network_despawn]. In all other cases no deletion happens, and the signal [signal network_despawn_request] is emitted instead.
+ </description>
+ </method>
+ <method name="send_spawn">
+ <return type="int" enum="Error" />
+ <argument index="0" name="peer_id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="path" type="NodePath" />
+ <argument index="3" name="data" type="PackedByteArray" default="PackedByteArray()" />
+ <description>
+ Sends a spawn request for the scene identified by [code]scene_id[/code] to the given [code]peer_id[/code] (see [method MultiplayerPeer.set_target_peer]). If the scene is configured as [constant SPAWN_MODE_SERVER] (see [method spawnable_config]) and the request is sent by the server (see [method is_network_server]), the receiving peer(s) will automatically instantiate that scene, add it to the [SceneTree] at the given [code]path[/code] and emit the signal [signal network_spawn]. In all other cases no instantiation happens, and the signal [signal network_spawn_request] is emitted instead.
+ </description>
+ </method>
+ <method name="spawnable_config">
+ <return type="int" enum="Error" />
+ <argument index="0" name="scene_id" type="int" />
+ <argument index="1" name="spawn_mode" type="int" enum="MultiplayerAPI.SpawnMode" />
+ <description>
+ Configures the MultiplayerAPI to track instances of the [PackedScene] idenfied by [code]scene_id[/code] (see [method ResourceLoader.get_resource_uid]) for the purpose of network replication. See [enum SpawnMode] for the possible configurations.
+ </description>
+ </method>
</methods>
<members>
<member name="allow_object_decoding" type="bool" setter="set_allow_object_decoding" getter="is_object_decoding_allowed" default="false">
@@ -94,6 +122,25 @@
Emitted when this MultiplayerAPI's [member network_peer] fails to establish a connection to a server. Only emitted on clients.
</description>
</signal>
+ <signal name="network_despawn">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="node" type="Node" />
+ <argument index="3" name="data" type="PackedByteArray" />
+ <description>
+ Emitted on a client before deleting a local Node upon receiving a despawn request from the server.
+ </description>
+ </signal>
+ <signal name="network_despawn_request">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="parent" type="Node" />
+ <argument index="3" name="name" type="String" />
+ <argument index="4" name="data" type="PackedByteArray" />
+ <description>
+ Emitted when a network despawn request has been received from a client, or for a [PackedScene] that has been configured as [constant SPAWN_MODE_CUSTOM].
+ </description>
+ </signal>
<signal name="network_peer_connected">
<argument index="0" name="id" type="int" />
<description>
@@ -113,6 +160,39 @@
Emitted when this MultiplayerAPI's [member network_peer] receive a [code]packet[/code] with custom data (see [method send_bytes]). ID is the peer ID of the peer that sent the packet.
</description>
</signal>
+ <signal name="network_spawn">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="node" type="Node" />
+ <argument index="3" name="data" type="PackedByteArray" />
+ <description>
+ Emitted on a client after a new Node is instantiated locally and added to the SceneTree upon receiving a spawn request from the server.
+ </description>
+ </signal>
+ <signal name="network_spawn_request">
+ <argument index="0" name="id" type="int" />
+ <argument index="1" name="scene_id" type="int" />
+ <argument index="2" name="parent" type="Node" />
+ <argument index="3" name="name" type="String" />
+ <argument index="4" name="data" type="PackedByteArray" />
+ <description>
+ Emitted when a network spawn request has been received from a client, or for a [PackedScene] that has been configured as [constant SPAWN_MODE_CUSTOM].
+ </description>
+ </signal>
+ <signal name="network_spawnable_added">
+ <argument index="0" name="scene_id" type="int" />
+ <argument index="1" name="node" type="Node" />
+ <description>
+ Emitted when an instance of a [PackedScene] that has been configured for networking enters the [SceneTree]. See [method spawnable_config].
+ </description>
+ </signal>
+ <signal name="network_spawnable_removed">
+ <argument index="0" name="scene_id" type="int" />
+ <argument index="1" name="node" type="Node" />
+ <description>
+ Emitted when an instance of a [PackedScene] that has been configured for networking leaves the [SceneTree]. See [method spawnable_config].
+ </description>
+ </signal>
<signal name="server_disconnected">
<description>
Emitted when this MultiplayerAPI's [member network_peer] disconnects from server. Only emitted on clients.
@@ -132,5 +212,14 @@
<constant name="RPC_MODE_PUPPET" value="3" enum="RPCMode">
Used with [method Node.rpc_config] to set a method to be called or a property to be changed only on puppets for this node. Analogous to the [code]puppet[/code] keyword. Only accepts calls or property changes from the node's network master, see [method Node.set_network_master].
</constant>
+ <constant name="SPAWN_MODE_NONE" value="0" enum="SpawnMode">
+ Used with [method spawnable_config] to identify a [PackedScene] that should not be replicated.
+ </constant>
+ <constant name="SPAWN_MODE_SERVER" value="1" enum="SpawnMode">
+ Used with [method spawnable_config] to identify a [PackedScene] that should be automatically replicated from server to clients.
+ </constant>
+ <constant name="SPAWN_MODE_CUSTOM" value="2" enum="SpawnMode">
+ Used with [method spawnable_config] to identify a [PackedScene] that can be manually replicated among peers.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/NativeExtension.xml b/doc/classes/NativeExtension.xml
index fa8575383c..ac3e8d53d8 100644
--- a/doc/classes/NativeExtension.xml
+++ b/doc/classes/NativeExtension.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeExtension" inherits="RefCounted" version="4.0">
+<class name="NativeExtension" inherits="Resource" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 983d8961fb..49901dc4d9 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -113,8 +113,9 @@
<argument index="0" name="target" type="Vector3" />
<argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<description>
- Rotates itself so that the local -Z axis points towards the [code]target[/code] position.
- The transform will first be rotated around the given [code]up[/code] vector, and then fully aligned to the target by a further rotation around an axis perpendicular to both the [code]target[/code] and [code]up[/code] vectors.
+ Rotates the node so that the local forward axis (-Z) points toward the [code]target[/code] position.
+ The local up axis (+Y) points as close to the [code]up[/code] vector as possible while staying perpendicular to the local forward axis. The resulting transform is orthogonal, and the scale is preserved. Non-uniform scaling may not work correctly.
+ The [code]target[/code] position cannot be the same as the node's position, the [code]up[/code] vector cannot be zero, and the direction from the node's position to the [code]target[/code] vector cannot be parallel to the [code]up[/code] vector.
Operations take place in global space.
</description>
</method>
@@ -124,7 +125,7 @@
<argument index="1" name="target" type="Vector3" />
<argument index="2" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<description>
- Moves the node to the specified [code]position[/code], and then rotates itself to point toward the [code]target[/code] as per [method look_at]. Operations take place in global space.
+ Moves the node to the specified [code]position[/code], and then rotates the node to point toward the [code]target[/code] as per [method look_at]. Operations take place in global space.
</description>
</method>
<method name="orthonormalize">
diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml
index ab3a04698f..4c6adfca32 100644
--- a/doc/classes/PhysicsDirectBodyState2D.xml
+++ b/doc/classes/PhysicsDirectBodyState2D.xml
@@ -137,6 +137,13 @@
Returns the current state of the space, useful for queries.
</description>
</method>
+ <method name="get_velocity_at_local_position" qualifiers="const">
+ <return type="Vector2" />
+ <argument index="0" name="local_position" type="Vector2" />
+ <description>
+ Returns the body's velocity at the given relative position, including both translation and rotation.
+ </description>
+ </method>
<method name="integrate_forces">
<return type="void" />
<description>
diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml
index 6af62c2bcc..271668e339 100644
--- a/doc/classes/PhysicsDirectBodyState3D.xml
+++ b/doc/classes/PhysicsDirectBodyState3D.xml
@@ -138,6 +138,13 @@
Returns the current state of the space, useful for queries.
</description>
</method>
+ <method name="get_velocity_at_local_position" qualifiers="const">
+ <return type="Vector3" />
+ <argument index="0" name="local_position" type="Vector3" />
+ <description>
+ Returns the body's velocity at the given relative position, including both translation and rotation.
+ </description>
+ </method>
<method name="integrate_forces">
<return type="void" />
<description>
diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml
index 7bca8afdda..d6b7318a06 100644
--- a/doc/classes/PhysicsServer3D.xml
+++ b/doc/classes/PhysicsServer3D.xml
@@ -572,6 +572,8 @@
<argument index="3" name="infinite_inertia" type="bool" />
<argument index="4" name="margin" type="float" default="0.001" />
<argument index="5" name="result" type="PhysicsTestMotionResult3D" default="null" />
+ <argument index="6" name="exclude_raycast_shapes" type="bool" default="true" />
+ <argument index="7" name="exclude" type="Array" default="[]" />
<description>
Returns [code]true[/code] if a collision would result from moving in the given direction from a given point in space. Margin increases the size of the shapes involved in the collision detection. [PhysicsTestMotionResult3D] can be passed to return additional information in.
</description>
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 43778df195..c329821646 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -142,7 +142,7 @@
<argument index="5" name="clear_color_values" type="PackedColorArray" default="PackedColorArray()" />
<argument index="6" name="clear_depth" type="float" default="1.0" />
<argument index="7" name="clear_stencil" type="int" default="0" />
- <argument index="8" name="region" type="Rect2" default="Rect2i(0, 0, 0, 0)" />
+ <argument index="8" name="region" type="Rect2" default="Rect2(0, 0, 0, 0)" />
<argument index="9" name="storage_textures" type="Array" default="[]" />
<description>
</description>
@@ -165,7 +165,7 @@
<argument index="6" name="clear_color_values" type="PackedColorArray" default="PackedColorArray()" />
<argument index="7" name="clear_depth" type="float" default="1.0" />
<argument index="8" name="clear_stencil" type="int" default="0" />
- <argument index="9" name="region" type="Rect2" default="Rect2i(0, 0, 0, 0)" />
+ <argument index="9" name="region" type="Rect2" default="Rect2(0, 0, 0, 0)" />
<argument index="10" name="storage_textures" type="RID[]" default="[]" />
<description>
</description>
@@ -217,7 +217,7 @@
<method name="draw_list_enable_scissor">
<return type="void" />
<argument index="0" name="draw_list" type="int" />
- <argument index="1" name="rect" type="Rect2" default="Rect2i(0, 0, 0, 0)" />
+ <argument index="1" name="rect" type="Rect2" default="Rect2(0, 0, 0, 0)" />
<description>
</description>
</method>
diff --git a/doc/classes/ResourceLoader.xml b/doc/classes/ResourceLoader.xml
index 3a3ce189d5..81e825194b 100644
--- a/doc/classes/ResourceLoader.xml
+++ b/doc/classes/ResourceLoader.xml
@@ -34,6 +34,13 @@
Returns the list of recognized extensions for a resource type.
</description>
</method>
+ <method name="get_resource_uid">
+ <return type="int" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ Returns the ID associated with a given resource path, or [code]-1[/code] when no such ID exists.
+ </description>
+ </method>
<method name="has_cached">
<return type="bool" />
<argument index="0" name="path" type="String" />
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 538e93d505..7bbcc5e0b5 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -21,7 +21,7 @@
<argument index="1" name="width" type="int" default="0" />
<argument index="2" name="height" type="int" default="0" />
<argument index="3" name="color" type="Color" default="Color(1, 1, 1, 1)" />
- <argument index="4" name="inline_align" type="int" enum="VAlign" default="0" />
+ <argument index="4" name="inline_align" type="int" enum="InlineAlign" default="5" />
<description>
Adds an image's opening and closing tags to the tag stack, optionally providing a [code]width[/code] and [code]height[/code] to resize the image and a [code]color[/code] to tint the image.
If [code]width[/code] or [code]height[/code] is set to 0, the image size will be adjusted in order to keep the original aspect ratio.
@@ -288,7 +288,7 @@
<method name="push_table">
<return type="void" />
<argument index="0" name="columns" type="int" />
- <argument index="1" name="inline_align" type="int" enum="VAlign" default="0" />
+ <argument index="1" name="inline_align" type="int" enum="InlineAlign" default="0" />
<description>
Adds a [code][table=columns,inline_align][/code] tag to the tag stack.
</description>
diff --git a/doc/classes/TextLine.xml b/doc/classes/TextLine.xml
index cc66f56d65..daa7298418 100644
--- a/doc/classes/TextLine.xml
+++ b/doc/classes/TextLine.xml
@@ -13,7 +13,7 @@
<return type="bool" />
<argument index="0" name="key" type="Variant" />
<argument index="1" name="size" type="Vector2" />
- <argument index="2" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="2" name="inline_align" type="int" enum="InlineAlign" default="5" />
<argument index="3" name="length" type="int" default="1" />
<description>
Adds inline object to the text buffer, [code]key[/code] must be unique. In the text, object is represented as [code]length[/code] object replacement characters.
@@ -122,7 +122,7 @@
<return type="bool" />
<argument index="0" name="key" type="Variant" />
<argument index="1" name="size" type="Vector2" />
- <argument index="2" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="2" name="inline_align" type="int" enum="InlineAlign" default="5" />
<description>
Sets new size and alignment of embedded object.
</description>
diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml
index 9050f9246a..811fe32eb2 100644
--- a/doc/classes/TextParagraph.xml
+++ b/doc/classes/TextParagraph.xml
@@ -13,7 +13,7 @@
<return type="bool" />
<argument index="0" name="key" type="Variant" />
<argument index="1" name="size" type="Vector2" />
- <argument index="2" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="2" name="inline_align" type="int" enum="InlineAlign" default="5" />
<argument index="3" name="length" type="int" default="1" />
<description>
Adds inline object to the text buffer, [code]key[/code] must be unique. In the text, object is represented as [code]length[/code] object replacement characters.
@@ -240,7 +240,7 @@
<return type="bool" />
<argument index="0" name="key" type="Variant" />
<argument index="1" name="size" type="Vector2" />
- <argument index="2" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="2" name="inline_align" type="int" enum="InlineAlign" default="5" />
<description>
Sets new size and alignment of embedded object.
</description>
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index dbf7ae93aa..ac56be4392 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -541,7 +541,7 @@
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="key" type="Variant" />
<argument index="2" name="size" type="Vector2" />
- <argument index="3" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="3" name="inline_align" type="int" enum="InlineAlign" default="5" />
<argument index="4" name="length" type="int" default="1" />
<description>
Adds inline object to the text buffer, [code]key[/code] must be unique. In the text, object is represented as [code]length[/code] object replacement characters.
@@ -817,7 +817,7 @@
<argument index="0" name="shaped" type="RID" />
<argument index="1" name="key" type="Variant" />
<argument index="2" name="size" type="Vector2" />
- <argument index="3" name="inline_align" type="int" enum="VAlign" default="1" />
+ <argument index="3" name="inline_align" type="int" enum="InlineAlign" default="5" />
<description>
Sets new size and alignment of embedded object.
</description>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index b9d3951b0a..948585aecb 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -107,7 +107,7 @@
</method>
<method name="looking_at" qualifiers="const">
<return type="Transform2D" />
- <argument index="0" name="target" type="Vector2" default="Transform2D(1, 0, 0, 1, 0, 0)" />
+ <argument index="0" name="target" type="Vector2" default="Vector2(0, 0)" />
<description>
Returns a copy of the transform rotated such that it's rotation on the X-axis points towards the [code]target[/code] position.
Operations take place in global space.
diff --git a/doc/classes/Transform3D.xml b/doc/classes/Transform3D.xml
index 53cdfd53c9..1c906f6a51 100644
--- a/doc/classes/Transform3D.xml
+++ b/doc/classes/Transform3D.xml
@@ -79,9 +79,8 @@
<argument index="0" name="target" type="Vector3" />
<argument index="1" name="up" type="Vector3" default="Vector3(0, 1, 0)" />
<description>
- Returns a copy of the transform rotated such that its -Z axis points towards the [code]target[/code] position.
- The transform will first be rotated around the given [code]up[/code] vector, and then fully aligned to the target by a further rotation around an axis perpendicular to both the [code]target[/code] and [code]up[/code] vectors.
- Operations take place in global space.
+ Returns a copy of the transform rotated such that the forward axis (-Z) points towards the [code]target[/code] position.
+ The up axis (+Y) points as close to the [code]up[/code] vector as possible while staying perpendicular to the forward axis. The resulting transform is orthonormalized. The existing rotation, scale, and skew information from the original transform is discarded. The [code]target[/code] and [code]up[/code] vectors cannot be zero, cannot be parallel to each other, and are defined in global/parent space.
</description>
</method>
<method name="operator !=" qualifiers="operator">
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index c2edab7e82..7b5cb2c459 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -169,7 +169,7 @@
<member name="audio_listener_enable_2d" type="bool" setter="set_as_audio_listener_2d" getter="is_audio_listener_2d" default="false">
If [code]true[/code], the viewport will process 2D audio streams.
</member>
- <member name="audio_listener_enable_3d" type="bool" setter="set_as_audio_listener" getter="is_audio_listener" default="false">
+ <member name="audio_listener_enable_3d" type="bool" setter="set_as_audio_listener_3d" getter="is_audio_listener_3d" default="false">
If [code]true[/code], the viewport will process 3D audio streams.
</member>
<member name="canvas_item_default_texture_filter" type="int" setter="set_default_canvas_item_texture_filter" getter="get_default_canvas_item_texture_filter" enum="Viewport.DefaultCanvasItemTextureFilter" default="1">
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index f504bad60d..775c999b15 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -35,6 +35,7 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include <share.h> // _SH_DENYNO
#include <shlwapi.h>
#include <windows.h>
@@ -77,8 +78,8 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
return ERR_INVALID_PARAMETER;
}
- /* pretty much every implementation that uses fopen as primary
- backend supports utf8 encoding */
+ /* Pretty much every implementation that uses fopen as primary
+ backend supports utf8 encoding. */
struct _stat st;
if (_wstat((LPCWSTR)(path.utf16().get_data()), &st) == 0) {
@@ -113,10 +114,10 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
path = path + ".tmp";
}
- errno_t errcode = _wfopen_s(&f, (LPCWSTR)(path.utf16().get_data()), mode_string);
+ f = _wfsopen((LPCWSTR)(path.utf16().get_data()), mode_string, _SH_DENYNO);
if (f == nullptr) {
- switch (errcode) {
+ switch (errno) {
case ENOENT: {
last_error = ERR_FILE_NOT_FOUND;
} break;
@@ -157,10 +158,10 @@ void FileAccessWindows::close() {
#else
if (!PathFileExistsW((LPCWSTR)(save_path.utf16().get_data()))) {
#endif
- //creating new file
+ // Creating new file
rename_error = _wrename((LPCWSTR)((save_path + ".tmp").utf16().get_data()), (LPCWSTR)(save_path.utf16().get_data())) != 0;
} else {
- //atomic replace for existing file
+ // Atomic replace for existing file
rename_error = !ReplaceFileW((LPCWSTR)(save_path.utf16().get_data()), (LPCWSTR)((save_path + ".tmp").utf16().get_data()), nullptr, 2 | 4, nullptr, nullptr);
}
if (rename_error) {
@@ -205,6 +206,7 @@ void FileAccessWindows::seek(uint64_t p_position) {
void FileAccessWindows::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
+
if (_fseeki64(f, p_position, SEEK_END)) {
check_errors();
}
@@ -237,6 +239,7 @@ bool FileAccessWindows::eof_reached() const {
uint8_t FileAccessWindows::get_8() const {
ERR_FAIL_COND_V(!f, 0);
+
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == WRITE) {
fflush(f);
@@ -273,6 +276,7 @@ Error FileAccessWindows::get_error() const {
void FileAccessWindows::flush() {
ERR_FAIL_COND(!f);
+
fflush(f);
if (prev_op == WRITE) {
prev_op = 0;
@@ -281,6 +285,7 @@ void FileAccessWindows::flush() {
void FileAccessWindows::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
+
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == READ) {
if (last_error != ERR_FILE_EOF) {
@@ -295,6 +300,7 @@ void FileAccessWindows::store_8(uint8_t p_dest) {
void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND(!f);
ERR_FAIL_COND(!p_src && p_length > 0);
+
if (flags == READ_WRITE || flags == WRITE_READ) {
if (prev_op == READ) {
if (last_error != ERR_FILE_EOF) {
@@ -307,10 +313,8 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, uint64_t p_length) {
}
bool FileAccessWindows::file_exists(const String &p_name) {
- FILE *g;
- //printf("opening file %s\n", p_fname.utf8().get_data());
String filename = fix_path(p_name);
- _wfopen_s(&g, (LPCWSTR)(filename.utf16().get_data()), L"rb");
+ FILE *g = _wfsopen((LPCWSTR)(filename.utf16().get_data()), L"rb", _SH_DENYNO);
if (g == nullptr) {
return false;
} else {
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
new file mode 100644
index 0000000000..5a4fcff0f8
--- /dev/null
+++ b/editor/editor_command_palette.cpp
@@ -0,0 +1,300 @@
+/*************************************************************************/
+/* editor_command_palette.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 "editor/editor_command_palette.h"
+#include "core/os/keyboard.h"
+#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
+#include "scene/gui/control.h"
+#include "scene/gui/tree.h"
+
+EditorCommandPalette *EditorCommandPalette::singleton = nullptr;
+
+float EditorCommandPalette::_score_path(const String &p_search, const String &p_path) {
+ float score = 0.9f + .1f * (p_search.length() / (float)p_path.length());
+
+ // Positive bias for matches close to the beginning of the file name.
+ int pos = p_path.findn(p_search);
+ if (pos != -1) {
+ return score * (1.0f - 0.1f * (float(pos) / p_path.length()));
+ }
+
+ // Positive bias for matches close to the end of the path.
+ pos = p_path.rfindn(p_search);
+ if (pos != -1) {
+ return score * (0.8f - 0.1f * (float(p_path.length() - pos) / p_path.length()));
+ }
+
+ // Remaining results belong to the same class of results.
+ return score * 0.69f;
+}
+
+void EditorCommandPalette::_update_command_search(const String &search_text) {
+ commands.get_key_list(&command_keys);
+ ERR_FAIL_COND(command_keys.is_empty());
+
+ const bool empty_search = search_text.is_empty();
+ Map<String, TreeItem *> sections;
+ TreeItem *first_section = nullptr;
+
+ // Filter possible candidates.
+ Vector<CommandEntry> entries;
+ for (int i = 0; i < command_keys.size(); i++) {
+ CommandEntry r;
+ r.key_name = command_keys[i];
+ r.display_name = commands[r.key_name].name;
+ r.shortcut_text = commands[r.key_name].shortcut;
+ if (!empty_search && search_text.is_subsequence_ofi(r.display_name)) {
+ r.score = _score_path(search_text, r.display_name.to_lower());
+ entries.push_back(r);
+ }
+ }
+
+ command_keys.clear();
+
+ TreeItem *root = search_options->get_root();
+ root->clear_children();
+
+ if (entries.size() > 0) {
+ if (!empty_search) {
+ SortArray<CommandEntry, CommandEntryComparator> sorter;
+ sorter.sort(entries.ptrw(), entries.size());
+ }
+
+ const int entry_limit = MIN(entries.size(), 300);
+ for (int i = 0; i < entry_limit; i++) {
+ String section_name = entries[i].key_name.get_slice("/", 0);
+ TreeItem *section;
+
+ if (sections.has(section_name)) {
+ section = sections[section_name];
+ } else {
+ section = search_options->create_item(root);
+
+ if (!first_section) {
+ first_section = section;
+ }
+
+ String item_name = section_name.capitalize();
+ section->set_text(0, item_name);
+
+ sections[section_name] = section;
+ section->set_custom_bg_color(0, search_options->get_theme_color("prop_subsection", "Editor"));
+ section->set_custom_bg_color(1, search_options->get_theme_color("prop_subsection", "Editor"));
+ }
+
+ TreeItem *ti = search_options->create_item(section);
+ String shortcut_text = entries[i].shortcut_text == "None" ? "" : entries[i].shortcut_text;
+ ti->set_text(0, entries[i].display_name);
+ ti->set_metadata(0, entries[i].key_name);
+ ti->set_text_align(1, TreeItem::TextAlign::ALIGN_RIGHT);
+ ti->set_text(1, shortcut_text);
+ Color c = Color(1, 1, 1, 0.5);
+ ti->set_custom_color(1, c);
+ }
+
+ TreeItem *to_select = first_section->get_first_child();
+ to_select->select(0);
+ to_select->set_as_cursor(0);
+ search_options->scroll_to_item(to_select);
+
+ get_ok_button()->set_disabled(false);
+ } else {
+ TreeItem *ti = search_options->create_item(root);
+ ti->set_text(0, TTR("No Matching Command"));
+ ti->set_metadata(0, "");
+ Color c = Color(0.5, 0.5, 0.5, 0.5);
+ ti->set_custom_color(0, c);
+ search_options->deselect_all();
+
+ get_ok_button()->set_disabled(true);
+ }
+}
+
+void EditorCommandPalette::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_command", "command_name", "key_name", "binded_callable", "shortcut_text"), &EditorCommandPalette::_add_command, DEFVAL("None"));
+ ClassDB::bind_method(D_METHOD("remove_command", "key_name"), &EditorCommandPalette::remove_command);
+}
+
+void EditorCommandPalette::_sbox_input(const Ref<InputEvent> &p_ie) {
+ Ref<InputEventKey> k = p_ie;
+ if (k.is_valid()) {
+ switch (k->get_keycode()) {
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PAGEUP:
+ case KEY_PAGEDOWN: {
+ search_options->call("_gui_input", k);
+ } break;
+ }
+ }
+}
+
+void EditorCommandPalette::_confirmed() {
+ TreeItem *selected_option = search_options->get_selected();
+ String command_key = selected_option != nullptr ? selected_option->get_metadata(0) : "";
+ if (command_key != "") {
+ hide();
+ execute_command(command_key);
+ }
+}
+
+void EditorCommandPalette::open_popup() {
+ popup_centered_clamped(Size2i(600, 440), 0.8f);
+ command_search_box->clear();
+ command_search_box->grab_focus();
+}
+
+void EditorCommandPalette::get_actions_list(List<String> *p_list) const {
+ commands.get_key_list(p_list);
+}
+
+void EditorCommandPalette::remove_command(String p_key_name) {
+ ERR_FAIL_COND_MSG(!commands.has(p_key_name), "The EditorAction '" + String(p_key_name) + "' Doesn't exists. Unable to remove it.");
+
+ commands.erase(p_key_name);
+}
+
+void EditorCommandPalette::add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, String p_shortcut_text) {
+ ERR_FAIL_COND_MSG(commands.has(p_key_name), "The EditorAction '" + String(p_command_name) + "' already exists. Unable to add it.");
+
+ const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * arguments.size());
+ for (int i = 0; i < arguments.size(); i++) {
+ argptrs[i] = &arguments[i];
+ }
+ Command p_command;
+ p_command.name = p_command_name;
+ p_command.callable = p_action.bind(argptrs, arguments.size());
+ p_command.shortcut = p_shortcut_text;
+
+ commands[p_key_name] = p_command;
+}
+
+void EditorCommandPalette::_add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text) {
+ ERR_FAIL_COND_MSG(commands.has(p_key_name), "The EditorAction '" + String(p_command_name) + "' already exists. Unable to add it.");
+
+ Command p_command;
+ p_command.name = p_command_name;
+ p_command.callable = p_binded_action;
+ p_command.shortcut = p_shortcut_text;
+
+ commands[p_key_name] = p_command;
+}
+
+void EditorCommandPalette::execute_command(String &p_command_key) {
+ ERR_FAIL_COND_MSG(!commands.has(p_command_key), p_command_key + " not found.");
+ commands[p_command_key].callable.call_deferred(nullptr, 0);
+}
+
+void EditorCommandPalette::register_shortcuts_as_command() {
+ const String *p_key = nullptr;
+ p_key = unregistered_shortcuts.next(p_key);
+ while (p_key != nullptr) {
+ String command_name = unregistered_shortcuts[*p_key].first;
+ Ref<Shortcut> p_shortcut = unregistered_shortcuts[*p_key].second;
+ Ref<InputEventShortcut> ev;
+ ev.instantiate();
+ ev->set_shortcut(p_shortcut);
+ String shortcut_text = String(p_shortcut->get_as_text());
+ add_command(command_name, *p_key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::unhandled_input), varray(ev, false), shortcut_text);
+ p_key = unregistered_shortcuts.next(p_key);
+ }
+ unregistered_shortcuts.clear();
+}
+
+Ref<Shortcut> EditorCommandPalette::add_shortcut_command(const String &p_command, const String &p_key, Ref<Shortcut> p_shortcut) {
+ if (is_inside_tree()) {
+ Ref<InputEventShortcut> ev;
+ ev.instantiate();
+ ev->set_shortcut(p_shortcut);
+ String shortcut_text = String(p_shortcut->get_as_text());
+ add_command(p_command, p_key, callable_mp(EditorNode::get_singleton()->get_viewport(), &Viewport::unhandled_input), varray(ev, false), shortcut_text);
+ } else {
+ const String key_name = String(p_key);
+ const String command_name = String(p_command);
+ Pair p_pair = Pair(command_name, p_shortcut);
+ unregistered_shortcuts[key_name] = p_pair;
+ }
+ return p_shortcut;
+}
+
+void EditorCommandPalette::_theme_changed() {
+ command_search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons"));
+}
+
+EditorCommandPalette *EditorCommandPalette::get_singleton() {
+ if (singleton == nullptr) {
+ singleton = memnew(EditorCommandPalette);
+ }
+ return singleton;
+}
+
+EditorCommandPalette::EditorCommandPalette() {
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ vbc->connect("theme_changed", callable_mp(this, &EditorCommandPalette::_theme_changed));
+ add_child(vbc);
+
+ command_search_box = memnew(LineEdit);
+ command_search_box->set_placeholder("search for a command");
+ command_search_box->set_placeholder_alpha(0.5);
+ command_search_box->connect("gui_input", callable_mp(this, &EditorCommandPalette::_sbox_input));
+ command_search_box->connect("text_changed", callable_mp(this, &EditorCommandPalette::_update_command_search));
+ command_search_box->connect("text_submitted", callable_mp(this, &EditorCommandPalette::_confirmed).unbind(1));
+ command_search_box->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ MarginContainer *margin_container_csb = memnew(MarginContainer);
+ margin_container_csb->add_child(command_search_box);
+ vbc->add_child(margin_container_csb);
+ register_text_enter(command_search_box);
+
+ search_options = memnew(Tree);
+ search_options->connect("item_activated", callable_mp(this, &EditorCommandPalette::_confirmed));
+ search_options->create_item();
+ search_options->set_hide_root(true);
+ search_options->set_hide_folding(true);
+ search_options->add_theme_constant_override("draw_guides", 1);
+ search_options->set_columns(2);
+ search_options->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ search_options->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ search_options->set_column_custom_minimum_width(0, int(8 * EDSCALE));
+
+ vbc->add_child(search_options, true);
+
+ set_hide_on_ok(false);
+}
+
+Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, uint32_t p_keycode, String p_command_name) {
+ if (p_command_name.is_empty()) {
+ p_command_name = p_name;
+ }
+
+ Ref<Shortcut> p_shortcut = ED_SHORTCUT(p_path, p_name, p_keycode);
+ EditorCommandPalette::get_singleton()->add_shortcut_command(p_command_name, p_path, p_shortcut);
+ return p_shortcut;
+}
diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h
new file mode 100644
index 0000000000..ddf897c250
--- /dev/null
+++ b/editor/editor_command_palette.h
@@ -0,0 +1,95 @@
+/*************************************************************************/
+/* editor_command_palette.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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 EDITOR_COMMAND_PALETTE_H
+#define EDITOR_COMMAND_PALETTE_H
+
+#include "core/os/thread_safe.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/shortcut.h"
+#include "scene/gui/tree.h"
+
+class EditorCommandPalette : public ConfirmationDialog {
+ GDCLASS(EditorCommandPalette, ConfirmationDialog);
+
+ static EditorCommandPalette *singleton;
+ LineEdit *command_search_box;
+ Tree *search_options;
+
+ struct Command {
+ Callable callable;
+ String name;
+ String shortcut;
+ };
+
+ struct CommandEntry {
+ String key_name;
+ String display_name;
+ String shortcut_text;
+ float score;
+ };
+
+ struct CommandEntryComparator {
+ _FORCE_INLINE_ bool operator()(const CommandEntry &A, const CommandEntry &B) const {
+ return A.score > B.score;
+ }
+ };
+
+ HashMap<String, Command> commands;
+ HashMap<String, Pair<String, Ref<Shortcut>>> unregistered_shortcuts;
+
+ List<String> command_keys;
+
+ void _update_command_search(const String &search_text);
+ float _score_path(const String &p_search, const String &p_path);
+ void _sbox_input(const Ref<InputEvent> &p_ie);
+ void _confirmed();
+ void _update_command_keys();
+ void _add_command(String p_command_name, String p_key_name, Callable p_binded_action, String p_shortcut_text = "None");
+ void _theme_changed();
+ EditorCommandPalette();
+
+protected:
+ static void _bind_methods();
+
+public:
+ void open_popup();
+ void get_actions_list(List<String> *p_list) const;
+ void add_command(String p_command_name, String p_key_name, Callable p_action, Vector<Variant> arguments, String p_shortcut_text = "None");
+ void execute_command(String &p_command_name);
+ void register_shortcuts_as_command();
+ Ref<Shortcut> add_shortcut_command(const String &p_command, const String &p_key, Ref<Shortcut> p_shortcut);
+ void remove_command(String p_key_name);
+ static EditorCommandPalette *get_singleton();
+};
+
+Ref<Shortcut> ED_SHORTCUT_AND_COMMAND(const String &p_path, const String &p_name, uint32_t p_keycode = 0, String p_command = "");
+
+#endif //EDITOR_COMMAND_PALETTE_H
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2126a7b8be..52672e9cc8 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -75,6 +75,7 @@
#include "editor/dependency_editor.h"
#include "editor/editor_about.h"
#include "editor/editor_audio_buses.h"
+#include "editor/editor_command_palette.h"
#include "editor/editor_export.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_file_system.h"
@@ -404,7 +405,7 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
- if (k.is_valid() && k->is_pressed() && !k->is_echo()) {
+ if ((k.is_valid() && k->is_pressed() && !k->is_echo()) || Object::cast_to<InputEventShortcut>(*p_event)) {
EditorPlugin *old_editor = editor_plugin_screen;
if (ED_IS_SHORTCUT("editor/next_tab", p_event)) {
@@ -435,6 +436,9 @@ void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
_editor_select_next();
} else if (ED_IS_SHORTCUT("editor/editor_prev", p_event)) {
_editor_select_prev();
+ } else if (ED_IS_SHORTCUT("editor/command_palette", p_event)) {
+ _open_command_palette();
+ } else {
}
if (old_editor != editor_plugin_screen) {
@@ -565,13 +569,15 @@ void EditorNode::_notification(int p_what) {
Engine::get_singleton()->set_editor_hint(true);
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
- get_tree()->get_root()->set_as_audio_listener(false);
+ get_tree()->get_root()->set_as_audio_listener_3d(false);
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->get_root()->set_snap_2d_transforms_to_pixel(false);
get_tree()->get_root()->set_snap_2d_vertices_to_pixel(false);
get_tree()->set_auto_accept_quit(false);
get_tree()->get_root()->connect("files_dropped", callable_mp(this, &EditorNode::_dropped_files));
+ command_palette->register_shortcuts_as_command();
+
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
@@ -1063,6 +1069,10 @@ void EditorNode::_editor_select_next() {
_editor_select(editor);
}
+void EditorNode::_open_command_palette() {
+ command_palette->open_popup();
+}
+
void EditorNode::_editor_select_prev() {
int editor = _get_current_main_editor();
@@ -2815,6 +2825,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case HELP_SEARCH: {
emit_signal(SNAME("request_help_search"), "");
} break;
+ case HELP_COMMAND_PALETTE: {
+ command_palette->open_popup();
+ } break;
case HELP_DOCS: {
OS::get_singleton()->shell_open("https://docs.godotengine.org/");
} break;
@@ -3802,6 +3815,7 @@ void EditorNode::register_editor_types() {
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
GDREGISTER_CLASS(EditorScenePostImport);
//ClassDB::register_type<EditorImportExport>();
+ GDREGISTER_CLASS(EditorCommandPalette);
GDREGISTER_CLASS(EditorDebuggerPlugin);
NativeExtensionManager::get_singleton()->initialize_extensions(NativeExtension::INITIALIZATION_LEVEL_EDITOR);
@@ -6129,9 +6143,9 @@ EditorNode::EditorNode() {
distraction_free = memnew(Button);
distraction_free->set_flat(true);
#ifdef OSX_ENABLED
- distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D));
+ distraction_free->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D));
#else
- distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11));
+ distraction_free->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F11));
#endif
distraction_free->set_tooltip(TTR("Toggle distraction-free mode."));
distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode));
@@ -6225,28 +6239,33 @@ EditorNode::EditorNode() {
ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD + KEY_TAB);
ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB);
ED_SHORTCUT("editor/filter_files", TTR("Filter Files..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_P);
+
+ command_palette = EditorCommandPalette::get_singleton();
+ command_palette->set_title(TTR("Command Palette"));
+ gui_base->add_child(command_palette);
+
PopupMenu *p;
file_menu->set_tooltip(TTR("Operations with scene files."));
p = file_menu->get_popup();
- p->add_shortcut(ED_SHORTCUT("editor/new_scene", TTR("New Scene"), KEY_MASK_CMD + KEY_N), FILE_NEW_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/new_inherited_scene", TTR("New Inherited Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_N), FILE_NEW_INHERITED_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTR("New Scene"), KEY_MASK_CMD + KEY_N), FILE_NEW_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTR("New Inherited Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_N), FILE_NEW_INHERITED_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTR("Open Scene..."), KEY_MASK_CMD + KEY_O), FILE_OPEN_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTR("Reopen Closed Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_T), FILE_OPEN_PREV);
p->add_submenu_item(TTR("Open Recent"), "RecentScenes", FILE_OPEN_RECENT);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_S), FILE_SAVE_AS_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_S), FILE_SAVE_ALL_SCENES);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_S), FILE_SAVE_AS_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_S), FILE_SAVE_ALL_SCENES);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN);
- p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_O), FILE_QUICK_OPEN_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN_SCRIPT);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_O), FILE_QUICK_OPEN_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN_SCRIPT);
p->add_separator();
PopupMenu *pm_export = memnew(PopupMenu);
@@ -6261,8 +6280,8 @@ EditorNode::EditorNode() {
p->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO, true);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE);
- p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_W), FILE_CLOSE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTR("Reload Saved Scene")), EDIT_RELOAD_SAVED_SCENE);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTR("Close Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_W), FILE_CLOSE);
recent_scenes = memnew(PopupMenu);
recent_scenes->set_name("RecentScenes");
@@ -6270,7 +6289,7 @@ EditorNode::EditorNode() {
recent_scenes->connect("id_pressed", callable_mp(this, &EditorNode::_open_recent_scene));
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/file_quit", TTR("Quit"), KEY_MASK_CMD + KEY_Q), FILE_QUIT, true);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTR("Quit"), KEY_MASK_CMD + KEY_Q), FILE_QUIT, true);
project_menu = memnew(MenuButton);
project_menu->set_flat(false);
@@ -6282,7 +6301,7 @@ EditorNode::EditorNode() {
p = project_menu->get_popup();
- p->add_shortcut(ED_SHORTCUT("editor/project_settings", TTR("Project Settings...")), RUN_SETTINGS);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTR("Project Settings..."), 0, TTR("Project Settings")), RUN_SETTINGS);
p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
@@ -6295,7 +6314,7 @@ EditorNode::EditorNode() {
vcs_actions_menu->add_item(TTR("Shut Down Version Control"), RUN_VCS_SHUT_DOWN);
p->add_separator();
- p->add_shortcut(ED_SHORTCUT("editor/export", TTR("Export...")), FILE_EXPORT_PROJECT);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTR("Export..."), 0, TTR("Export")), FILE_EXPORT_PROJECT);
p->add_item(TTR("Install Android Build Template..."), FILE_INSTALL_ANDROID_SOURCE);
p->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER);
@@ -6313,9 +6332,9 @@ EditorNode::EditorNode() {
p->add_separator();
p->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTR("Reload Current Project")), RUN_RELOAD_CURRENT_PROJECT);
#ifdef OSX_ENABLED
- p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
#else
- p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Q), RUN_PROJECT_MANAGER, true);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Q), RUN_PROJECT_MANAGER, true);
#endif
menu_hb->add_spacer();
@@ -6342,9 +6361,9 @@ EditorNode::EditorNode() {
p = settings_menu->get_popup();
#ifdef OSX_ENABLED
- p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings..."), KEY_MASK_CMD + KEY_COMMA), SETTINGS_PREFERENCES);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTR("Editor Settings..."), KEY_MASK_CMD + KEY_COMMA), SETTINGS_PREFERENCES);
#else
- p->add_shortcut(ED_SHORTCUT("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTR("Editor Settings...")), SETTINGS_PREFERENCES);
#endif
p->add_separator();
@@ -6355,15 +6374,15 @@ EditorNode::EditorNode() {
p->add_submenu_item(TTR("Editor Layout"), "Layouts");
p->add_separator();
#ifdef OSX_ENABLED
- p->add_shortcut(ED_SHORTCUT("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CMD | KEY_F12), EDITOR_SCREENSHOT);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CMD | KEY_F12), EDITOR_SCREENSHOT);
#else
- p->add_shortcut(ED_SHORTCUT("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CTRL | KEY_F12), EDITOR_SCREENSHOT);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTR("Take Screenshot"), KEY_MASK_CTRL | KEY_F12), EDITOR_SCREENSHOT);
#endif
p->set_item_tooltip(p->get_item_count() - 1, TTR("Screenshots are stored in the Editor Data/Settings Folder."));
#ifdef OSX_ENABLED
- p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
#else
- p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
+ p->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
#endif
#if defined(WINDOWS_ENABLED) && defined(WINDOWS_SUBSYSTEM_CONSOLE)
// The console can only be toggled if the application was built for the console subsystem,
@@ -6396,20 +6415,20 @@ EditorNode::EditorNode() {
p = help_menu->get_popup();
p->connect("id_pressed", callable_mp(this, &EditorNode::_menu_option));
#ifdef OSX_ENABLED
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE), HELP_SEARCH);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTR("Search Help"), KEY_MASK_ALT | KEY_SPACE), HELP_SEARCH);
#else
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTR("Search Help"), KEY_F1), HELP_SEARCH);
#endif
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/q&a", TTR("Questions & Answers")), HELP_QA);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT("editor/community", TTR("Community")), HELP_COMMUNITY);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Godot"), SNAME("EditorIcons")), ED_SHORTCUT("editor/about", TTR("About Godot")), HELP_ABOUT);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Godot"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/about", TTR("About Godot")), HELP_ABOUT);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
HBoxContainer *play_hb = memnew(HBoxContainer);
menu_hb->add_child(play_hb);
@@ -6423,9 +6442,9 @@ EditorNode::EditorNode() {
play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY));
play_button->set_tooltip(TTR("Play the project."));
#ifdef OSX_ENABLED
- play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_MASK_CMD | KEY_B));
+ play_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), KEY_MASK_CMD | KEY_B));
#else
- play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5));
+ play_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), KEY_F5));
#endif
pause_button = memnew(Button);
@@ -6469,9 +6488,9 @@ EditorNode::EditorNode() {
play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_SCENE));
play_scene_button->set_tooltip(TTR("Play the edited scene."));
#ifdef OSX_ENABLED
- play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_MASK_CMD | KEY_R));
+ play_scene_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), KEY_MASK_CMD | KEY_R));
#else
- play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6));
+ play_scene_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), KEY_F6));
#endif
play_custom_scene_button = memnew(Button);
@@ -6483,9 +6502,9 @@ EditorNode::EditorNode() {
play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_PLAY_CUSTOM_SCENE));
play_custom_scene_button->set_tooltip(TTR("Play custom scene"));
#ifdef OSX_ENABLED
- play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R));
+ play_custom_scene_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_R));
#else
- play_custom_scene_button->set_shortcut(ED_SHORTCUT("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5));
+ play_custom_scene_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F5));
#endif
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
@@ -7020,19 +7039,21 @@ EditorNode::EditorNode() {
ResourceLoader::set_load_callback(_resource_loaded);
#ifdef OSX_ENABLED
- ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_ALT | KEY_1);
- ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
- ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
- ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_ALT | KEY_4);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_ALT | KEY_1);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_ALT | KEY_2);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_ALT | KEY_3);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_ALT | KEY_4);
+ ED_SHORTCUT("editor/command_palette", TTR("Open Command Palette"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_P);
#else
// Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock.
- ED_SHORTCUT("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_CTRL | KEY_F1);
- ED_SHORTCUT("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_CTRL | KEY_F2);
- ED_SHORTCUT("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_CTRL | KEY_F3);
- ED_SHORTCUT("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_CTRL | KEY_F4);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTR("Open 2D Editor"), KEY_MASK_CTRL | KEY_F1);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_3d", TTR("Open 3D Editor"), KEY_MASK_CTRL | KEY_F2);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_script", TTR("Open Script Editor"), KEY_MASK_CTRL | KEY_F3);
+ ED_SHORTCUT_AND_COMMAND("editor/editor_assetlib", TTR("Open Asset Library"), KEY_MASK_CTRL | KEY_F4);
+ ED_SHORTCUT("editor/command_palette", TTR("Open Command Palette"), KEY_MASK_CTRL | KEY_MASK_SHIFT | KEY_P);
#endif
- ED_SHORTCUT("editor/editor_next", TTR("Open the next Editor"));
- ED_SHORTCUT("editor/editor_prev", TTR("Open the previous Editor"));
+ ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTR("Open the next Editor"));
+ ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTR("Open the previous Editor"));
screenshot_timer = memnew(Timer);
screenshot_timer->set_one_shot(true);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 6b91856a59..fed4d23704 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -32,6 +32,7 @@
#define EDITOR_NODE_H
#include "core/templates/safe_refcount.h"
+#include "editor/editor_command_palette.h"
#include "editor/editor_data.h"
#include "editor/editor_export.h"
#include "editor/editor_folding.h"
@@ -55,6 +56,7 @@ class Control;
class DependencyEditor;
class DependencyErrorDialog;
class EditorAbout;
+class EditorCommandPalette;
class EditorExport;
class EditorFeatureProfileManager;
class EditorFileServer;
@@ -192,6 +194,7 @@ private:
EDITOR_OPEN_SCREENSHOT,
HELP_SEARCH,
+ HELP_COMMAND_PALETTE,
HELP_DOCS,
HELP_QA,
HELP_REPORT_A_BUG,
@@ -342,6 +345,7 @@ private:
CenterContainer *tabs_center;
EditorQuickOpen *quick_open;
EditorQuickOpen *quick_run;
+ EditorCommandPalette *command_palette;
HBoxContainer *main_editor_button_vb;
Vector<Button *> main_editor_buttons;
@@ -505,6 +509,7 @@ private:
void _quick_opened();
void _quick_run();
+ void _open_command_palette();
void _run(bool p_current = false, const String &p_custom = "");
void _run_native(const Ref<EditorExportPreset> &p_preset);
@@ -703,6 +708,7 @@ public:
EditorInspector *get_inspector() { return inspector_dock->get_inspector(); }
Container *get_inspector_dock_addon_area() { return inspector_dock->get_addon_area(); }
ScriptCreateDialog *get_script_create_dialog() { return scene_tree_dock->get_script_create_dialog(); }
+ EditorCommandPalette *get_editor_command_palette() { return command_palette; }
ProjectSettingsEditor *get_project_settings() { return project_settings; }
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 07e9357e67..b71a3944fc 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -310,6 +310,10 @@ bool EditorInterface::is_distraction_free_mode_enabled() const {
return EditorNode::get_singleton()->is_distraction_free_mode_enabled();
}
+EditorCommandPalette *EditorInterface::get_command_palette() const {
+ return EditorNode::get_singleton()->get_editor_command_palette();
+}
+
EditorInterface *EditorInterface::singleton = nullptr;
void EditorInterface::_bind_methods() {
@@ -340,6 +344,7 @@ void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorInterface::get_current_path);
ClassDB::bind_method(D_METHOD("get_file_system_dock"), &EditorInterface::get_file_system_dock);
ClassDB::bind_method(D_METHOD("get_editor_paths"), &EditorInterface::get_editor_paths);
+ ClassDB::bind_method(D_METHOD("get_command_palette"), &EditorInterface::get_command_palette);
ClassDB::bind_method(D_METHOD("set_plugin_enabled", "plugin", "enabled"), &EditorInterface::set_plugin_enabled);
ClassDB::bind_method(D_METHOD("is_plugin_enabled", "plugin"), &EditorInterface::is_plugin_enabled);
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index 2e1dd0a0c1..d665278144 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -45,6 +45,7 @@
class EditorNode;
class Node3D;
class Camera3D;
+class EditorCommandPalette;
class EditorSelection;
class EditorExport;
class EditorSettings;
@@ -87,6 +88,8 @@ public:
Array get_open_scenes() const;
ScriptEditor *get_script_editor();
+ EditorCommandPalette *get_command_palette() const;
+
void select_file(const String &p_file);
String get_selected_path() const;
String get_current_path() const;
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 0d714065e3..08dd37bc73 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1345,7 +1345,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("folder_icon_modulate", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7));
theme->set_color("files_disabled", "FileDialog", font_disabled_color);
- // color picker
+ // ColorPicker
theme->set_constant("margin", "ColorPicker", popup_margin_size);
theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE);
theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE);
@@ -1358,6 +1358,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon("ColorPickerBarArrow", "EditorIcons"));
theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon("PickerCursor", "EditorIcons"));
+ // ColorPickerButton
theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
// Information on 3D viewport
diff --git a/editor/icons/PrismMesh.svg b/editor/icons/PrismMesh.svg
index cca52bb7b0..0fd169cc8c 100644
--- a/editor/icons/PrismMesh.svg
+++ b/editor/icons/PrismMesh.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.9824 1.002a1.0001 1.0001 0 0 0 -.81445.44336l-5.9727 8.9609-.027344.03906a1 1 0 0 0 -.0625.10742 1 1 0 0 0 .44727 1.3418l6 3a1.0001 1.0001 0 0 0 .89453 0l6-3a1 1 0 0 0 .44726-1.3418 1 1 0 0 0 -.0625-.10742l-6-9a1.0001 1.0001 0 0 0 -.84961-.44336zm-.98242 4.3008v7.0801l-3.5391-1.7715zm2 0 3.5391 5.3086-3.5391 1.7715z" fill="#ffca5f"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3.9168678 1.8860265c-.3598509 1.0771598-1.9743383 5.9072035-2.95075512 8.8641335-.15505871.56144.26297692 1.081021.77506042 1.256186 1.9729807.978051 3.9341568 1.98391 5.9144721 2.944682.5872542.201411 1.0933197-.27019 1.6046594-.478049 1.7521944-.878995 3.5092364-1.748814 5.2583944-2.633556.53543-.305954.598247-1.041459.264856-1.51829-.991782-1.9723689-1.966021-3.9544106-2.968743-5.9207481-.320568-.4259931-.882722-.5397422-1.322158-.8066387-1.7413894-.8632626-4.7187151-2.3492561-5.2199521-2.59935915-.501237-.2501031-.9959833-.18552039-1.3558341.89163945zm1.6236276 1.4766588 4.2114703 2.1046892-2.3703904 7.1132625-4.2114703-2.104688zm5.6257546 4.2135626 1.479141 2.9582811-2.9603737 1.481232z" fill="#ffca5f"/></svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index b615c73422..54b93edcdd 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -1414,7 +1414,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
//animation->set_loop(true);
//create animation tracks
- Vector<float> base_snapshots;
+ Vector<real_t> base_snapshots;
float f = 0;
float snapshot_interval = 1.0 / bake_fps; //should be customizable somewhere...
@@ -1466,7 +1466,7 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
animation->track_set_path(track, path);
animation->track_set_imported(track, true); //helps merging later
- Vector<float> snapshots = base_snapshots;
+ Vector<real_t> snapshots = base_snapshots;
if (nm.anim_tracks.size() == 1) {
//use snapshot keys from anim track instead, because this was most likely exported baked
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index 24c950fdee..fe98a91ab3 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -92,7 +92,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
PopupMenu *animations_menu;
Vector<String> animations_to_add;
float add_point_pos;
- Vector<float> points;
+ Vector<real_t> points;
bool dragging_selected_attempt;
bool dragging_selected;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index c440064898..7fe12089c8 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4073,7 +4073,7 @@ void CanvasItemEditor::_popup_warning_depop(Control *p_control) {
info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10);
}
-void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) {
+void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const double p_duration) {
Timer *timer;
if (!popup_temporarily_timers.has(p_control)) {
timer = memnew(Timer);
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 1f59dfbc49..495cd5f515 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -56,7 +56,7 @@ public:
Transform2D pre_drag_xform;
Rect2 pre_drag_rect;
- List<float> pre_drag_bones_length;
+ List<real_t> pre_drag_bones_length;
List<Dictionary> pre_drag_bones_undo_state;
Dictionary undo_state;
@@ -540,7 +540,7 @@ private:
VSplitContainer *bottom_split;
void _update_context_menu_stylebox();
- void _popup_warning_temporarily(Control *p_control, const float p_duration);
+ void _popup_warning_temporarily(Control *p_control, const double p_duration);
void _popup_warning_depop(Control *p_control);
void _set_owner_for_node_and_children(Node *p_node, Node *p_owner);
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index d7618b973e..d47bd2d410 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -386,7 +386,7 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() {
Vector<Vector3> vertices;
Vector<Vector3> normals;
Vector<Vector2> uvs;
- Vector<float> tangents;
+ Vector<real_t> tangents;
Basis tt = Basis(Vector3(0, 1, 0), Math_PI * 0.5);
for (int i = 1; i <= lats; i++) {
@@ -635,7 +635,7 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const
Ref<AudioStreamPlayback> playback = stream->instance_playback();
ERR_FAIL_COND_V(playback.is_null(), Ref<Texture2D>());
- float len_s = stream->get_length();
+ real_t len_s = stream->get_length();
if (len_s == 0) {
len_s = 60; //one minute audio if no length specified
}
@@ -649,8 +649,8 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const
playback->stop();
for (int i = 0; i < w; i++) {
- float max = -1000;
- float min = 1000;
+ real_t max = -1000;
+ real_t min = 1000;
int from = uint64_t(i) * frame_length / w;
int to = (uint64_t(i) + 1) * frame_length / w;
to = MIN(to, frame_length);
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index 5184e837ce..efec5a709d 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -60,7 +60,7 @@ void GPUParticles2DEditorPlugin::_file_selected(const String &p_file) {
void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
switch (p_idx) {
case MENU_GENERATE_VISIBILITY_RECT: {
- float gen_time = particles->get_lifetime();
+ double gen_time = particles->get_lifetime();
if (gen_time < 1.0) {
generate_seconds->set_value(1.0);
} else {
@@ -100,7 +100,7 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) {
}
void GPUParticles2DEditorPlugin::_generate_visibility_rect() {
- float time = generate_seconds->get_value();
+ double time = generate_seconds->get_value();
float running = 0.0;
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 8576082597..fff25b6f59 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -282,9 +282,9 @@ void GPUParticles3DEditor::_menu_option(int p_option) {
}
void GPUParticles3DEditor::_generate_aabb() {
- float time = generate_seconds->get_value();
+ double time = generate_seconds->get_value();
- float running = 0.0;
+ double running = 0.0;
EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time));
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 53f602460c..64f46f2b1a 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -63,7 +63,7 @@ class EditorNode3DGizmo : public Node3DGizmo {
Vector<Vector3> secondary_handles;
Vector<int> secondary_handle_ids;
- float selectable_icon_size;
+ real_t selectable_icon_size;
bool billboard_handle;
bool valid;
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 931c50fc44..7acf5c2013 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2735,7 +2735,7 @@ void Node3DEditorViewport::_notification(int p_what) {
if (show_fps) {
cpu_time_history[cpu_time_history_index] = RS::get_singleton()->viewport_get_measured_render_time_cpu(viewport->get_viewport_rid());
cpu_time_history_index = (cpu_time_history_index + 1) % FRAME_TIME_HISTORY;
- float cpu_time = 0.0;
+ double cpu_time = 0.0;
for (int i = 0; i < FRAME_TIME_HISTORY; i++) {
cpu_time += cpu_time_history[i];
}
@@ -2745,7 +2745,7 @@ void Node3DEditorViewport::_notification(int p_what) {
gpu_time_history[gpu_time_history_index] = RS::get_singleton()->viewport_get_measured_render_time_gpu(viewport->get_viewport_rid());
gpu_time_history_index = (gpu_time_history_index + 1) % FRAME_TIME_HISTORY;
- float gpu_time = 0.0;
+ double gpu_time = 0.0;
for (int i = 0; i < FRAME_TIME_HISTORY; i++) {
gpu_time += gpu_time_history[i];
}
@@ -2769,7 +2769,7 @@ void Node3DEditorViewport::_notification(int p_what) {
frame_time_gradient->get_color_at_offset(
Math::range_lerp(gpu_time, 0, 30, 0, 1)));
- const float fps = 1000.0 / gpu_time;
+ const double fps = 1000.0 / gpu_time;
fps_label->set_text(vformat(TTR("FPS: %d"), fps));
// Middle point is at 60 FPS.
fps_label->add_theme_color_override(
@@ -3187,7 +3187,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
bool current = view_menu->get_popup()->is_item_checked(idx);
current = !current;
- viewport->set_as_audio_listener(current);
+ viewport->set_as_audio_listener_3d(current);
view_menu->get_popup()->set_item_checked(idx, current);
} break;
@@ -3634,7 +3634,7 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) {
bool listener = p_state["listener"];
int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
- viewport->set_as_audio_listener(listener);
+ viewport->set_as_audio_listener_3d(listener);
view_menu->get_popup()->set_item_checked(idx, listener);
}
if (p_state.has("doppler")) {
@@ -3718,7 +3718,7 @@ Dictionary Node3DEditorViewport::get_state() const {
} else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS))) {
d["display_mode"] = VIEW_DISPLAY_SHADELESS;
}
- d["listener"] = viewport->is_audio_listener();
+ d["listener"] = viewport->is_audio_listener_3d();
d["doppler"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER));
d["gizmos"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS));
d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION));
@@ -4363,7 +4363,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
if (p_index == 0) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER), true);
- viewport->set_as_audio_listener(true);
+ viewport->set_as_audio_listener_3d(true);
}
name = "";
@@ -6820,7 +6820,7 @@ void Node3DEditor::clear() {
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(Node3DEditorViewport::VIEW_AUDIO_LISTENER), i == 0);
- viewports[i]->viewport->set_as_audio_listener(i == 0);
+ viewports[i]->viewport->set_as_audio_listener_3d(i == 0);
}
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index cb2edbcbc1..0c1456aaf8 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -166,9 +166,9 @@ public:
};
private:
- float cpu_time_history[FRAME_TIME_HISTORY];
+ double cpu_time_history[FRAME_TIME_HISTORY];
int cpu_time_history_index;
- float gpu_time_history[FRAME_TIME_HISTORY];
+ double gpu_time_history[FRAME_TIME_HISTORY];
int gpu_time_history_index;
int index;
@@ -336,7 +336,7 @@ private:
String last_message;
String message;
- float message_time;
+ double message_time;
void set_message(String p_message, float p_time = 5);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 5bbe56a800..bb8b87ed83 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -33,6 +33,7 @@
#include "core/math/expression.h"
#include "core/os/keyboard.h"
#include "editor/debugger/editor_debugger_node.h"
+#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -1941,15 +1942,15 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I);
ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I);
- ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F);
+ ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F);
#ifdef OSX_ENABLED
ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G);
ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G);
- ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F);
+ ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F);
#else
ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3);
ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3);
- ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R);
+ ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R);
#endif
ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 4202d8b611..3de2ffc137 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -397,7 +397,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi
bone_shape->set_transform(capsule_transform);
Transform3D body_transform;
- body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin);
+ body_transform.basis = Basis::looking_at(child_rest.origin);
body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height));
Transform3D joint_transform;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 9a41a100bd..f960da6732 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -408,10 +408,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id));
Control *custom_editor = nullptr;
- int port_offset = 0;
+ int port_offset = 1;
+
+ Control *content_offset = memnew(Control);
+ content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE));
+ node->add_child(content_offset);
if (is_group) {
- port_offset += 2;
+ port_offset += 1;
}
if (is_resizable) {
@@ -448,7 +452,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") {
//shortcut
VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
- node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]);
+ node->set_slot(1, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]);
if (!vsnode->is_use_prop_slots()) {
return;
}
@@ -582,7 +586,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (is_curve) {
VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0);
VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0);
- node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]);
+ node->set_slot(1, true, port_left, type_color[port_left], true, port_right, type_color[port_right]);
VisualShaderEditor::get_singleton()->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size);
}
@@ -594,10 +598,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
if (is_group) {
- offset = memnew(Control);
- offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE));
- node->add_child(offset);
-
if (group_node->is_editable()) {
HBoxContainer *hb2 = memnew(HBoxContainer);
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index a1deae92a4..96fcb4fe29 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -351,51 +351,64 @@ void PropertySelector::_item_selected() {
String class_type;
if (type != Variant::NIL) {
class_type = Variant::get_type_name(type);
-
- } else {
+ } else if (base_type != String()) {
class_type = base_type;
+ } else if (instance) {
+ class_type = instance->get_class();
}
DocTools *dd = EditorHelp::get_doc_data();
String text;
-
if (properties) {
- String at_class = class_type;
-
- while (at_class != String()) {
- Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class);
+ while (class_type != String()) {
+ Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type);
if (E) {
for (int i = 0; i < E->get().properties.size(); i++) {
if (E->get().properties[i].name == name) {
text = DTR(E->get().properties[i].description);
+ break;
}
}
}
- at_class = ClassDB::get_parent_class(at_class);
+ if (text != String()) {
+ break;
+ }
+
+ // The property may be from a parent class, keep looking.
+ class_type = ClassDB::get_parent_class(class_type);
}
} else {
- String at_class = class_type;
-
- while (at_class != String()) {
- Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(at_class);
+ while (class_type != String()) {
+ Map<String, DocData::ClassDoc>::Element *E = dd->class_list.find(class_type);
if (E) {
for (int i = 0; i < E->get().methods.size(); i++) {
if (E->get().methods[i].name == name) {
text = DTR(E->get().methods[i].description);
+ break;
}
}
}
- at_class = ClassDB::get_parent_class(at_class);
+ if (text != String()) {
+ break;
+ }
+
+ // The method may be from a parent class, keep looking.
+ class_type = ClassDB::get_parent_class(class_type);
}
}
- if (text == String()) {
- return;
+ if (text != String()) {
+ // Display both property name and description, since the help bit may be displayed
+ // far away from the location (especially if the dialog was resized to be taller).
+ help_bit->set_text(vformat("[b]%s[/b]: %s", name, text));
+ help_bit->get_rich_text()->set_self_modulate(Color(1, 1, 1, 1));
+ } else {
+ // Use nested `vformat()` as translators shouldn't interfere with BBCode tags.
+ help_bit->set_text(vformat(TTR("No description available for %s."), vformat("[b]%s[/b]", name)));
+ help_bit->get_rich_text()->set_self_modulate(Color(1, 1, 1, 0.5));
}
-
- help_bit->set_text(text);
}
void PropertySelector::_hide_requested() {
diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp
index beae0c9c91..7e6f154fab 100644
--- a/editor/shader_create_dialog.cpp
+++ b/editor/shader_create_dialog.cpp
@@ -78,26 +78,18 @@ void ShaderCreateDialog::_update_theme() {
void ShaderCreateDialog::_update_language_info() {
language_data.clear();
- List<StringName> classes;
- classes.push_front(SNAME("Shader"));
- classes.push_front(SNAME("VisualShader"));
-
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- language_data.push_back(ShaderTypeData());
- }
-
- int idx = 0;
- for (List<ShaderTypeData>::Element *E = language_data.front(); E; E = E->next()) {
- if (idx == int(SHADER_TYPE_TEXT)) {
- E->get().use_templates = true;
- E->get().extensions.push_back("gdshader");
- E->get().default_extension = "gdshader";
+ for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+ ShaderTypeData data;
+ if (i == int(SHADER_TYPE_TEXT)) {
+ data.use_templates = true;
+ data.extensions.push_back("gdshader");
+ data.default_extension = "gdshader";
} else {
- E->get().default_extension = "tres";
+ data.default_extension = "tres";
}
- E->get().extensions.push_back("res");
- E->get().extensions.push_back("tres");
- idx++;
+ data.extensions.push_back("res");
+ data.extensions.push_back("tres");
+ language_data.push_back(data);
}
}
@@ -216,6 +208,7 @@ void ShaderCreateDialog::_load_exist() {
}
void ShaderCreateDialog::_language_changed(int p_language) {
+ current_language = p_language;
ShaderTypeData data = language_data[p_language];
String selected_ext = "." + data.default_extension;
@@ -304,20 +297,19 @@ void ShaderCreateDialog::_path_changed(const String &p_path) {
is_path_valid = false;
is_new_shader_created = true;
- String path_error = _validate_path(p_path, false);
+ String path_error = _validate_path(p_path);
if (path_error != "") {
_msg_path_valid(false, path_error);
_update_dialog();
return;
}
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
if (f->file_exists(p)) {
is_new_shader_created = false;
_msg_path_valid(true, TTR("File exists, it will be reused."));
}
- memdelete(f);
is_path_valid = true;
_update_dialog();
@@ -345,7 +337,7 @@ void ShaderCreateDialog::config(const String &p_base_path, bool p_built_in_enabl
_path_changed(file_path->get_text());
}
-String ShaderCreateDialog::_validate_path(const String &p_path, bool p_file_must_exist) {
+String ShaderCreateDialog::_validate_path(const String &p_path) {
String p = p_path.strip_edges();
if (p == "") {
@@ -360,29 +352,24 @@ String ShaderCreateDialog::_validate_path(const String &p_path, bool p_file_must
return TTR("Path is not local.");
}
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (d->change_dir(p.get_base_dir()) != OK) {
- memdelete(d);
return TTR("Invalid base path.");
}
- memdelete(d);
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (f->dir_exists(p)) {
- memdelete(f);
return TTR("A directory with the same name exists.");
- } else if (p_file_must_exist && !f->file_exists(p)) {
- memdelete(f);
- return TTR("File does not exist.");
}
- memdelete(f);
String extension = p.get_extension();
- List<String> extensions;
+ Set<String> extensions;
- for (int l = 0; l < SHADER_TYPE_MAX; l++) {
- for (List<String>::Element *E = language_data[l].extensions.front(); E; E = E->next()) {
- extensions.push_back(E->get());
+ for (int i = 0; i < SHADER_TYPE_MAX; i++) {
+ for (const String &ext : language_data[i].extensions) {
+ if (!extensions.has(ext)) {
+ extensions.insert(ext);
+ }
}
}
@@ -390,16 +377,18 @@ String ShaderCreateDialog::_validate_path(const String &p_path, bool p_file_must
bool found = false;
bool match = false;
- int index = 0;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
+
+ for (const String &ext : extensions) {
+ if (ext.nocasecmp_to(extension) == 0) {
found = true;
- if (E->get() == data.default_extension) {
- match = true;
+ for (const String &lang_ext : language_data[current_language].extensions) {
+ if (lang_ext.nocasecmp_to(extension) == 0) {
+ match = true;
+ break;
+ }
}
break;
}
- index++;
}
if (!found) {
@@ -409,11 +398,6 @@ String ShaderCreateDialog::_validate_path(const String &p_path, bool p_file_must
return TTR("Wrong extension chosen.");
}
- String path_error = ScriptServer::get_language(language_menu->get_selected())->validate_path(p);
- if (path_error != "") {
- return path_error;
- }
-
return "";
}
@@ -468,7 +452,7 @@ void ShaderCreateDialog::_update_dialog() {
if (is_built_in) {
get_ok_button()->set_text(TTR("Create"));
- _msg_path_valid(true, TTR("Built-in script (into scene file)."));
+ _msg_path_valid(true, TTR("Built-in shader (into scene file)."));
} else if (is_new_shader_created) {
get_ok_button()->set_text(TTR("Create"));
if (is_path_valid) {
@@ -585,8 +569,8 @@ ShaderCreateDialog::ShaderCreateDialog() {
// Modes.
mode_menu = memnew(OptionButton);
- for (const List<String>::Element *E = ShaderTypes::get_singleton()->get_types_list().front(); E; E = E->next()) {
- mode_menu->add_item(E->get().capitalize());
+ for (const String &type_name : ShaderTypes::get_singleton()->get_types_list()) {
+ mode_menu->add_item(type_name.capitalize());
}
gc->add_child(memnew(Label(TTR("Mode:"))));
gc->add_child(mode_menu);
diff --git a/editor/shader_create_dialog.h b/editor/shader_create_dialog.h
index cc338cd6b5..6962fa3d8d 100644
--- a/editor/shader_create_dialog.h
+++ b/editor/shader_create_dialog.h
@@ -94,7 +94,7 @@ class ShaderCreateDialog : public ConfirmationDialog {
void _mode_changed(int p_mode = 0);
void _browse_path();
void _file_selected(const String &p_file);
- String _validate_path(const String &p_path, bool p_file_must_exist);
+ String _validate_path(const String &p_path);
virtual void ok_pressed() override;
void _create_new();
void _load_exist();
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index bfac0df5b0..ba57de303e 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -12,6 +12,8 @@ thirdparty_obj = []
if env["builtin_bullet"]:
# Build only version 2 for now (as of 2.89)
# Sync file list with relevant upstream CMakeLists.txt for each folder.
+ if env["float"] == "64":
+ env.Append(CPPDEFINES=["BT_USE_DOUBLE_PRECISION=1"])
thirdparty_dir = "#thirdparty/bullet/"
bullet2_src = [
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index e07be14c5b..fc876a81cf 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -842,12 +842,12 @@ PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_bod
return BulletPhysicsDirectBodyState3D::get_singleton(body);
}
-bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes, p_exclude);
}
int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index d34d619ba2..7f0934e679 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -253,7 +253,7 @@ public:
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override;
virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
/* SOFT BODY API */
diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp
index 399b102284..1f962772e7 100644
--- a/modules/bullet/godot_result_callbacks.cpp
+++ b/modules/bullet/godot_result_callbacks.cpp
@@ -135,6 +135,10 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox
if (m_self_object->has_collision_exception(gObj) || gObj->has_collision_exception(m_self_object)) {
return false;
}
+
+ if (m_exclude->has(gObj->get_self())) {
+ return false;
+ }
}
return true;
} else {
diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h
index 9216322108..96a649d77a 100644
--- a/modules/bullet/godot_result_callbacks.h
+++ b/modules/bullet/godot_result_callbacks.h
@@ -100,11 +100,13 @@ public:
struct GodotKinClosestConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback {
public:
const RigidBodyBullet *m_self_object;
+ const Set<RID> *m_exclude;
const bool m_infinite_inertia;
- GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia) :
+ GodotKinClosestConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, const RigidBodyBullet *p_self_object, bool p_infinite_inertia, const Set<RID> *p_exclude) :
btCollisionWorld::ClosestConvexResultCallback(convexFromWorld, convexToWorld),
m_self_object(p_self_object),
+ m_exclude(p_exclude),
m_infinite_inertia(p_infinite_inertia) {}
virtual bool needsCollision(btBroadphaseProxy *proxy0) const;
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index ce39d4f0df..0d2cd1f5a0 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -114,6 +114,16 @@ Transform3D BulletPhysicsDirectBodyState3D::get_transform() const {
return body->get_transform();
}
+Vector3 BulletPhysicsDirectBodyState3D::get_velocity_at_local_position(const Vector3 &p_position) const {
+ btVector3 local_position;
+ G_TO_B(p_position, local_position);
+
+ Vector3 velocity;
+ B_TO_G(body->btBody->getVelocityInLocalPoint(local_position), velocity);
+
+ return velocity;
+}
+
void BulletPhysicsDirectBodyState3D::add_central_force(const Vector3 &p_force) {
body->apply_central_force(p_force);
}
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 606df7134b..5e102d8b05 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -110,6 +110,8 @@ public:
virtual void set_transform(const Transform3D &p_transform) override;
virtual Transform3D get_transform() const override;
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override;
+
virtual void add_central_force(const Vector3 &p_force) override;
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override;
virtual void add_torque(const Vector3 &p_torque) override;
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 583900e6bc..c6d835742d 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -908,7 +908,7 @@ static Ref<StandardMaterial3D> red_mat;
static Ref<StandardMaterial3D> blue_mat;
#endif
-bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
#if debug_test_motion
/// Yes I know this is not good, but I've used it as fast debugging hack.
/// I'm leaving it here just for speedup the other eventual debugs
@@ -948,7 +948,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
btVector3 initial_recover_motion(0, 0, 0);
{ /// Phase one - multi shapes depenetration using margin
for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) {
- if (!recover_from_penetration(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, initial_recover_motion)) {
+ if (!recover_from_penetration(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, initial_recover_motion, nullptr, p_exclude)) {
break;
}
}
@@ -1000,7 +1000,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
break;
}
- GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia);
+ GodotKinClosestConvexResultCallback btResult(shape_world_from.getOrigin(), shape_world_to.getOrigin(), p_body, p_infinite_inertia, &p_exclude);
btResult.m_collisionFilterGroup = p_body->get_collision_layer();
btResult.m_collisionFilterMask = p_body->get_collision_mask();
@@ -1023,7 +1023,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform3D &p
btVector3 __rec(0, 0, 0);
RecoverResult r_recover_result;
- has_penetration = recover_from_penetration(p_body, body_transform, 1, p_infinite_inertia, __rec, &r_recover_result);
+ has_penetration = recover_from_penetration(p_body, body_transform, 1, p_infinite_inertia, __rec, &r_recover_result, p_exclude);
// Parse results
if (r_result) {
@@ -1173,7 +1173,7 @@ public:
}
};
-bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
+bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result, const Set<RID> &p_exclude) {
// Calculate the cumulative AABB of all shapes of the kinematic body
btVector3 aabb_min, aabb_max;
bool shapes_found = false;
@@ -1242,6 +1242,12 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
for (int i = recover_broad_result.results.size() - 1; 0 <= i; --i) {
btCollisionObject *otherObject = recover_broad_result.results[i].collision_object;
+
+ CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(otherObject->getUserPointer());
+ if (p_exclude.has(gObj->get_self())) {
+ continue;
+ }
+
if (p_infinite_inertia && !otherObject->isStaticOrKinematicObject()) {
otherObject->activate(); // Force activation of hitten rigid, soft body
continue;
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 36d0538e6b..2070e0e633 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -188,7 +188,7 @@ public:
real_t get_linear_damp() const { return linear_damp; }
real_t get_angular_damp() const { return angular_damp; }
- bool test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ bool test_body_motion(RigidBodyBullet *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude = Set<RID>());
int test_ray_separation(RigidBodyBullet *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
private:
@@ -209,7 +209,7 @@ private:
RecoverResult() {}
};
- bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr);
+ bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr, const Set<RID> &p_exclude = Set<RID>());
/// This is an API that recover a kinematic object from penetration
/// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions
bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = nullptr);
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index de7de09f00..0106f230eb 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -83,14 +83,14 @@ private:
Vector<Vector3> vertices;
Vector<Vector3> normals;
Vector<Vector2> uvs;
- Vector<float> tans;
+ Vector<real_t> tans;
Ref<Material> material;
int last_added = 0;
Vector3 *verticesw = nullptr;
Vector3 *normalsw = nullptr;
Vector2 *uvsw = nullptr;
- float *tansw = nullptr;
+ real_t *tansw = nullptr;
};
//mikktspace callbacks
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
index 8b4b1e08b3..dcea476275 100644
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ b/modules/fbx/data/fbx_mesh_data.cpp
@@ -433,7 +433,7 @@ void FBXMeshData::sanitize_vertex_weights(const ImportState &state) {
{
// Sort
- real_t *weights_ptr = vm->weights.ptrw();
+ float *weights_ptr = vm->weights.ptrw();
int *bones_ptr = vm->bones.ptrw();
for (int i = 0; i < vm->weights.size(); i += 1) {
for (int x = i + 1; x < vm->weights.size(); x += 1) {
@@ -449,7 +449,7 @@ void FBXMeshData::sanitize_vertex_weights(const ImportState &state) {
// Resize
vm->weights.resize(max_vertex_influence_count);
vm->bones.resize(max_vertex_influence_count);
- real_t *weights_ptr = vm->weights.ptrw();
+ float *weights_ptr = vm->weights.ptrw();
int *bones_ptr = vm->bones.ptrw();
for (int i = initial_size; i < max_vertex_influence_count; i += 1) {
weights_ptr[i] = 0.0;
diff --git a/modules/fbx/data/fbx_mesh_data.h b/modules/fbx/data/fbx_mesh_data.h
index 7486c5c59c..24db4a5469 100644
--- a/modules/fbx/data/fbx_mesh_data.h
+++ b/modules/fbx/data/fbx_mesh_data.h
@@ -64,7 +64,7 @@ struct SurfaceData {
};
struct VertexWeightMapping {
- Vector<real_t> weights;
+ Vector<float> weights;
Vector<int> bones;
// This extra vector is used because the bone id is computed in a second step.
// TODO Get rid of this extra step is a good idea.
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index f3a0e9603f..26d3aed702 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -114,9 +114,25 @@ void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder)
#endif
bool NativeScript::inherits_script(const Ref<Script> &p_script) const {
-#ifndef _MSC_VER
-#warning inheritance needs to be implemented in NativeScript
-#endif
+ Ref<NativeScript> ns = p_script;
+ if (ns.is_null()) {
+ return false;
+ }
+
+ const NativeScriptDesc *other_s = ns->get_script_desc();
+ if (!other_s) {
+ return false;
+ }
+
+ const NativeScriptDesc *s = get_script_desc();
+
+ while (s) {
+ if (s == other_s) {
+ return true;
+ }
+ s = s->base_data;
+ }
+
return false;
}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index 7fc8178e34..5380858582 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -139,9 +139,20 @@ bool PluginScript::can_instantiate() const {
}
bool PluginScript::inherits_script(const Ref<Script> &p_script) const {
-#ifndef _MSC_VER
-#warning inheritance needs to be implemented in PluginScript
-#endif
+ Ref<PluginScript> ps = p_script;
+ if (ps.is_null()) {
+ return false;
+ }
+
+ const PluginScript *s = this;
+
+ while (s) {
+ if (s == p_script.ptr()) {
+ return true;
+ }
+ s = Object::cast_to<PluginScript>(s->_ref_base_parent.ptr());
+ }
+
return false;
}
diff --git a/modules/gdnative/text/text_server_gdnative.cpp b/modules/gdnative/text/text_server_gdnative.cpp
index 81dd570bcb..d54b1a47df 100644
--- a/modules/gdnative/text/text_server_gdnative.cpp
+++ b/modules/gdnative/text/text_server_gdnative.cpp
@@ -449,12 +449,12 @@ bool TextServerGDNative::shaped_text_add_string(RID p_shaped, const String &p_te
return interface->shaped_text_add_string(data, (godot_rid *)&p_shaped, (const godot_string *)&p_text, (const godot_rid **)p_fonts.ptr(), p_size, (const godot_dictionary *)&p_opentype_features, (const godot_string *)&p_language);
}
-bool TextServerGDNative::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) {
+bool TextServerGDNative::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
ERR_FAIL_COND_V(interface == nullptr, false);
return interface->shaped_text_add_object(data, (godot_rid *)&p_shaped, (const godot_variant *)&p_key, (const godot_vector2 *)&p_size, (godot_int)p_inline_align, p_length);
}
-bool TextServerGDNative::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align) {
+bool TextServerGDNative::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
ERR_FAIL_COND_V(interface == nullptr, false);
return interface->shaped_text_resize_object(data, (godot_rid *)&p_shaped, (const godot_variant *)&p_key, (const godot_vector2 *)&p_size, (godot_int)p_inline_align);
}
diff --git a/modules/gdnative/text/text_server_gdnative.h b/modules/gdnative/text/text_server_gdnative.h
index 7a0725f3d9..a2eb944499 100644
--- a/modules/gdnative/text/text_server_gdnative.h
+++ b/modules/gdnative/text/text_server_gdnative.h
@@ -154,8 +154,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) override;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) override;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 7c9d08b782..fe827a5b72 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -107,7 +107,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
// Locate class by constructing the path to it and following that path
GDScriptParser::ClassNode *class_type = p_datatype.class_type;
if (class_type) {
- if (class_type->fqcn.begins_with(main_script->path) || (!main_script->name.is_empty() && class_type->fqcn.begins_with(main_script->name))) {
+ if ((!main_script->path.is_empty() && class_type->fqcn.begins_with(main_script->path)) || (!main_script->name.is_empty() && class_type->fqcn.begins_with(main_script->name))) {
// Local class.
List<StringName> names;
while (class_type->outer) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index a500dfd51a..a21167ad95 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2480,7 +2480,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
switch (dictionary->style) {
case DictionaryNode::LUA_TABLE:
if (key != nullptr && key->type != Node::IDENTIFIER) {
- push_error("Expected identifier as dictionary key.");
+ push_error("Expected identifier as LUA-style dictionary key.");
+ advance();
+ break;
}
if (!match(GDScriptTokenizer::Token::EQUAL)) {
if (match(GDScriptTokenizer::Token::COLON)) {
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index be44f66423..ff0579a11c 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -43,6 +43,7 @@
#include "gltf_texture.h"
#include "core/crypto/crypto_core.h"
+#include "core/error/error_macros.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/json.h"
@@ -4469,9 +4470,9 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) {
const Dictionary &spot = d["spot"];
light->inner_cone_angle = spot["innerConeAngle"];
light->outer_cone_angle = spot["outerConeAngle"];
- ERR_FAIL_COND_V_MSG(light->inner_cone_angle >= light->outer_cone_angle, ERR_PARSE_ERROR, "The inner angle must be smaller than the outer angle.");
+ ERR_CONTINUE_MSG(light->inner_cone_angle >= light->outer_cone_angle, "The inner angle must be smaller than the outer angle.");
} else if (type != "point" && type != "directional") {
- ERR_FAIL_V_MSG(ERR_PARSE_ERROR, "Light type is unknown.");
+ ERR_CONTINUE_MSG(ERR_PARSE_ERROR, "Light type is unknown.");
}
state->lights.push_back(light);
@@ -5380,15 +5381,16 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> state, Node *scene_parent
// and attach it to the bone_attachment
scene_parent = bone_attachment;
}
-
- // We still have not managed to make a node
if (gltf_node->mesh >= 0) {
current_node = _generate_mesh_instance(state, scene_parent, node_index);
} else if (gltf_node->camera >= 0) {
current_node = _generate_camera(state, scene_parent, node_index);
} else if (gltf_node->light >= 0) {
current_node = _generate_light(state, scene_parent, node_index);
- } else {
+ }
+
+ // We still have not managed to make a node.
+ if (!current_node) {
current_node = _generate_spatial(state, scene_parent, node_index);
}
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index fa4888f843..66816f32d1 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1161,7 +1161,7 @@ bool TextServerAdvanced::shaped_text_add_string(RID p_shaped, const String &p_te
return true;
}
-bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) {
+bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
_THREAD_SAFE_METHOD_
ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -1191,7 +1191,7 @@ bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, con
return true;
}
-bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align) {
+bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
_THREAD_SAFE_METHOD_
ShapedTextData *sd = shaped_owner.getornull(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -1222,34 +1222,10 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key,
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->objects[key].rect.position.x = sd->width;
sd->width += sd->objects[key].rect.size.x;
- switch (sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.y / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y);
- } break;
- }
sd->glyphs.write[i].advance = sd->objects[key].rect.size.x;
} else {
sd->objects[key].rect.position.y = sd->width;
sd->width += sd->objects[key].rect.size.y;
- switch (sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.x / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x);
- } break;
- }
sd->glyphs.write[i].advance = sd->objects[key].rect.size.y;
}
} else {
@@ -1279,35 +1255,71 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key,
}
// Align embedded objects to baseline.
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) {
if ((E->get().pos >= sd->start) && (E->get().pos < sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = sd->descent;
+ } break;
+ }
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = sd->descent - E->get().rect.size.y;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
} break;
}
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
}
+ sd->ascent = full_ascent;
+ sd->descent = full_descent;
}
return true;
}
@@ -1404,33 +1416,9 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->objects[key].rect.position.x = new_sd->width;
new_sd->width += new_sd->objects[key].rect.size.x;
- switch (new_sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.y / 2));
- new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y);
- } break;
- }
} else {
new_sd->objects[key].rect.position.y = new_sd->width;
new_sd->width += new_sd->objects[key].rect.size.y;
- switch (new_sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.x / 2));
- new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x);
- } break;
- }
}
} else {
if (prev_rid != gl.font_rid) {
@@ -1464,37 +1452,72 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng
}
// Align embedded objects to baseline.
+ float full_ascent = new_sd->ascent;
+ float full_descent = new_sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = new_sd->objects.front(); E; E = E->next()) {
if ((E->get().pos >= new_sd->start) && (E->get().pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -new_sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-new_sd->ascent + new_sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = new_sd->descent;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = new_sd->descent - E->get().rect.size.y;
+ }
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
} break;
}
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -new_sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-new_sd->ascent + new_sd->descent) / 2;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = new_sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = new_sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
}
+ new_sd->ascent = full_ascent;
+ new_sd->descent = full_descent;
}
-
new_sd->valid = true;
return shaped_owner.make_rid(new_sd);
@@ -2473,33 +2496,9 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->objects[span.embedded_key].rect.position.x = sd->width;
sd->width += sd->objects[span.embedded_key].rect.size.x;
- switch (sd->objects[span.embedded_key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y);
- } break;
- }
} else {
sd->objects[span.embedded_key].rect.position.y = sd->width;
sd->width += sd->objects[span.embedded_key].rect.size.y;
- switch (sd->objects[span.embedded_key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x);
- } break;
- }
}
Glyph gl;
gl.start = span.start;
@@ -2539,34 +2538,69 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) {
}
// Align embedded objects to baseline.
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-sd->ascent + sd->descent) / 2;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = sd->descent - E->get().rect.size.y;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = sd->descent;
+ } break;
+ }
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
} break;
}
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
-
+ sd->ascent = full_ascent;
+ sd->descent = full_descent;
sd->valid = true;
return sd->valid;
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 3c4f840bfd..c54686c114 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -216,8 +216,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) override;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) override;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 004cbc2bb3..b60bf8e8d3 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -661,7 +661,7 @@ bool TextServerFallback::shaped_text_add_string(RID p_shaped, const String &p_te
return true;
}
-bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) {
+bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
_THREAD_SAFE_METHOD_
ShapedTextData *sd = shaped_owner.getornull(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -691,7 +691,7 @@ bool TextServerFallback::shaped_text_add_object(RID p_shaped, Variant p_key, con
return true;
}
-bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align) {
+bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
_THREAD_SAFE_METHOD_
ShapedTextData *sd = shaped_owner.getornull(p_shaped);
ERR_FAIL_COND_V(!sd, false);
@@ -724,34 +724,10 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->objects[key].rect.position.x = sd->width;
sd->width += sd->objects[key].rect.size.x;
- switch (sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.y / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[key].rect.size.y);
- } break;
- }
sd->glyphs.write[i].advance = sd->objects[key].rect.size.x;
} else {
sd->objects[key].rect.position.y = sd->width;
sd->width += sd->objects[key].rect.size.y;
- switch (sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[key].rect.size.x / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[key].rect.size.x);
- } break;
- }
sd->glyphs.write[i].advance = sd->objects[key].rect.size.y;
}
} else {
@@ -784,35 +760,71 @@ bool TextServerFallback::shaped_text_resize_object(RID p_shaped, Variant p_key,
}
// Align embedded objects to baseline.
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) {
if ((E->get().pos >= sd->start) && (E->get().pos < sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = sd->descent;
+ } break;
+ }
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = sd->descent - E->get().rect.size.y;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
} break;
}
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
}
+ sd->ascent = full_ascent;
+ sd->descent = full_descent;
}
return true;
}
@@ -869,33 +881,9 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
if (new_sd->orientation == ORIENTATION_HORIZONTAL) {
new_sd->objects[key].rect.position.x = new_sd->width;
new_sd->width += new_sd->objects[key].rect.size.x;
- switch (new_sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.y / 2));
- new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.y);
- } break;
- }
} else {
new_sd->objects[key].rect.position.y = new_sd->width;
new_sd->width += new_sd->objects[key].rect.size.y;
- switch (new_sd->objects[key].inline_align) {
- case VALIGN_TOP: {
- new_sd->ascent = MAX(new_sd->ascent, new_sd->objects[key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- new_sd->ascent = MAX(new_sd->ascent, Math::round(new_sd->objects[key].rect.size.x / 2));
- new_sd->descent = MAX(new_sd->descent, Math::round(new_sd->objects[key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- new_sd->descent = MAX(new_sd->descent, new_sd->objects[key].rect.size.x);
- } break;
- }
}
} else {
const FontDataFallback *fd = font_owner.getornull(gl.font_rid);
@@ -923,35 +911,72 @@ RID TextServerFallback::shaped_text_substr(RID p_shaped, int p_start, int p_leng
}
}
+ // Align embedded objects to baseline.
+ float full_ascent = new_sd->ascent;
+ float full_descent = new_sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = new_sd->objects.front(); E; E = E->next()) {
if ((E->get().pos >= new_sd->start) && (E->get().pos < new_sd->end)) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -new_sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-new_sd->ascent + new_sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = new_sd->descent - E->get().rect.size.y;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = new_sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -new_sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-new_sd->ascent + new_sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = new_sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = new_sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
}
+ new_sd->ascent = full_ascent;
+ new_sd->descent = full_descent;
}
new_sd->valid = true;
@@ -1336,33 +1361,9 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
sd->objects[span.embedded_key].rect.position.x = sd->width;
sd->width += sd->objects[span.embedded_key].rect.size.x;
- switch (sd->objects[span.embedded_key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.y);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.y / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.y);
- } break;
- }
} else {
sd->objects[span.embedded_key].rect.position.y = sd->width;
sd->width += sd->objects[span.embedded_key].rect.size.y;
- switch (sd->objects[span.embedded_key].inline_align) {
- case VALIGN_TOP: {
- sd->ascent = MAX(sd->ascent, sd->objects[span.embedded_key].rect.size.x);
- } break;
- case VALIGN_CENTER: {
- sd->ascent = MAX(sd->ascent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
- sd->descent = MAX(sd->descent, Math::round(sd->objects[span.embedded_key].rect.size.x / 2));
- } break;
- case VALIGN_BOTTOM: {
- sd->descent = MAX(sd->descent, sd->objects[span.embedded_key].rect.size.x);
- } break;
- }
}
Glyph gl;
gl.start = span.start;
@@ -1456,34 +1457,69 @@ bool TextServerFallback::shaped_text_shape(RID p_shaped) {
}
// Align embedded objects to baseline.
+ float full_ascent = sd->ascent;
+ float full_descent = sd->descent;
for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) {
if (sd->orientation == ORIENTATION_HORIZONTAL) {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.y = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.y = -(E->get().rect.size.y / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.y = (-sd->ascent + sd->descent) / 2;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.y = sd->descent - E->get().rect.size.y;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.y = 0;
+ } break;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.y = sd->descent;
+ } break;
+ }
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.y -= E->get().rect.size.y / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
} break;
}
+ full_ascent = MAX(full_ascent, -E->get().rect.position.y);
+ full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y);
} else {
- switch (E->get().inline_align) {
- case VALIGN_TOP: {
+ switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) {
+ case INLINE_ALIGN_TO_TOP: {
E->get().rect.position.x = -sd->ascent;
} break;
- case VALIGN_CENTER: {
- E->get().rect.position.x = -(E->get().rect.size.x / 2);
+ case INLINE_ALIGN_TO_CENTER: {
+ E->get().rect.position.x = (-sd->ascent + sd->descent) / 2;
+ } break;
+ case INLINE_ALIGN_TO_BASELINE: {
+ E->get().rect.position.x = 0;
} break;
- case VALIGN_BOTTOM: {
- E->get().rect.position.x = sd->descent - E->get().rect.size.x;
+ case INLINE_ALIGN_TO_BOTTOM: {
+ E->get().rect.position.x = sd->descent;
} break;
}
+ switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) {
+ case INLINE_ALIGN_BOTTOM_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x;
+ } break;
+ case INLINE_ALIGN_CENTER_TO: {
+ E->get().rect.position.x -= E->get().rect.size.x / 2;
+ } break;
+ case INLINE_ALIGN_TOP_TO: {
+ //NOP
+ } break;
+ }
+ full_ascent = MAX(full_ascent, -E->get().rect.position.x);
+ full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x);
}
}
-
+ sd->ascent = full_ascent;
+ sd->descent = full_descent;
sd->valid = true;
return sd->valid;
}
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index b70c8f4ec0..e3bbde76d4 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -165,8 +165,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const override;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") override;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) override;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) override;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) override;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) override;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override;
virtual RID shaped_text_get_parent(RID p_shaped) const override;
diff --git a/modules/vhacd/register_types.cpp b/modules/vhacd/register_types.cpp
index 3d7aaee921..2b48e94604 100644
--- a/modules/vhacd/register_types.cpp
+++ b/modules/vhacd/register_types.cpp
@@ -33,7 +33,7 @@
#include "thirdparty/vhacd/public/VHACD.h"
static Vector<Vector<Face3>> convex_decompose(const Vector<Face3> &p_faces, int p_max_convex_hulls = -1) {
- Vector<float> vertices;
+ Vector<real_t> vertices;
vertices.resize(p_faces.size() * 9);
Vector<uint32_t> indices;
indices.resize(p_faces.size() * 3);
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index 9fa49b8a1d..cded1e587c 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -93,7 +93,7 @@ String VisualScriptYield::get_text() const {
class VisualScriptNodeInstanceYield : public VisualScriptNodeInstance {
public:
VisualScriptYield::YieldMode mode;
- float wait_time;
+ double wait_time;
virtual int get_working_memory_size() const { return 1; } //yield needs at least 1
//virtual bool is_output_port_unsequenced(int p_idx) const { return false; }
@@ -159,7 +159,7 @@ VisualScriptYield::YieldMode VisualScriptYield::get_yield_mode() {
return yield_mode;
}
-void VisualScriptYield::set_wait_time(float p_time) {
+void VisualScriptYield::set_wait_time(double p_time) {
if (wait_time == p_time) {
return;
}
@@ -167,7 +167,7 @@ void VisualScriptYield::set_wait_time(float p_time) {
ports_changed_notify();
}
-float VisualScriptYield::get_wait_time() {
+double VisualScriptYield::get_wait_time() {
return wait_time;
}
diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h
index fa596173a6..6005ff30b0 100644
--- a/modules/visual_script/visual_script_yield_nodes.h
+++ b/modules/visual_script/visual_script_yield_nodes.h
@@ -47,7 +47,7 @@ public:
private:
YieldMode yield_mode;
- float wait_time;
+ double wait_time;
protected:
virtual void _validate_property(PropertyInfo &property) const override;
@@ -73,8 +73,8 @@ public:
void set_yield_mode(YieldMode p_mode);
YieldMode get_yield_mode();
- void set_wait_time(float p_time);
- float get_wait_time();
+ void set_wait_time(double p_time);
+ double get_wait_time();
virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 73aa013701..974f4d3018 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -318,8 +318,16 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
- Input::get_singleton()->set_mouse_position(wd.mouse_pos);
+ if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CAPTURED) {
+ const NSRect contentRect = [wd.window_view frame];
+ NSRect pointInWindowRect = NSMakeRect(contentRect.size.width / 2, contentRect.size.height / 2, 0, 0);
+ NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
+ CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y };
+ CGWarpMouseCursorPosition(lMouseWarpPos);
+ } else {
+ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
+ Input::get_singleton()->set_mouse_position(wd.mouse_pos);
+ }
DS_OSX->window_focused = true;
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN);
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index da2ab6ada8..026f0a85a6 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -159,12 +159,12 @@ void AnimatedSprite2D::_notification(int p_what) {
return;
}
- float speed = frames->get_animation_speed(animation) * speed_scale;
+ double speed = frames->get_animation_speed(animation) * speed_scale;
if (speed == 0) {
return; //do nothing
}
- float remaining = get_process_delta_time();
+ double remaining = get_process_delta_time();
while (remaining) {
if (timeout <= 0) {
@@ -205,7 +205,7 @@ void AnimatedSprite2D::_notification(int p_what) {
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
- float to_process = MIN(timeout, remaining);
+ double to_process = MIN(timeout, remaining);
remaining -= to_process;
timeout -= to_process;
}
@@ -310,8 +310,8 @@ int AnimatedSprite2D::get_frame() const {
return frame;
}
-void AnimatedSprite2D::set_speed_scale(float p_speed_scale) {
- float elapsed = _get_frame_duration() - timeout;
+void AnimatedSprite2D::set_speed_scale(double p_speed_scale) {
+ double elapsed = _get_frame_duration() - timeout;
speed_scale = MAX(p_speed_scale, 0.0f);
@@ -320,7 +320,7 @@ void AnimatedSprite2D::set_speed_scale(float p_speed_scale) {
timeout -= elapsed;
}
-float AnimatedSprite2D::get_speed_scale() const {
+double AnimatedSprite2D::get_speed_scale() const {
return speed_scale;
}
@@ -402,9 +402,9 @@ bool AnimatedSprite2D::is_playing() const {
return playing;
}
-float AnimatedSprite2D::_get_frame_duration() {
+double AnimatedSprite2D::_get_frame_duration() {
if (frames.is_valid() && frames->has_animation(animation)) {
- float speed = frames->get_animation_speed(animation) * speed_scale;
+ double speed = frames->get_animation_speed(animation) * speed_scale;
if (speed > 0) {
return 1.0 / speed;
}
diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h
index ef0027edf1..0769b19b50 100644
--- a/scene/2d/animated_sprite_2d.h
+++ b/scene/2d/animated_sprite_2d.h
@@ -56,7 +56,7 @@ class AnimatedSprite2D : public Node2D {
void _res_changed();
- float _get_frame_duration();
+ double _get_frame_duration();
void _reset_timeout();
void _set_playing(bool p_playing);
bool _is_playing() const;
@@ -94,8 +94,8 @@ public:
void set_frame(int p_frame);
int get_frame() const;
- void set_speed_scale(float p_speed_scale);
- float get_speed_scale() const;
+ void set_speed_scale(double p_speed_scale);
+ double get_speed_scale() const;
void set_centered(bool p_center);
bool is_centered() const;
diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index a341ba69ac..ced1c5cb81 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -65,7 +65,7 @@ void CPUParticles2D::set_amount(int p_amount) {
particle_order.resize(p_amount);
}
-void CPUParticles2D::set_lifetime(float p_lifetime) {
+void CPUParticles2D::set_lifetime(double p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
}
@@ -74,7 +74,7 @@ void CPUParticles2D::set_one_shot(bool p_one_shot) {
one_shot = p_one_shot;
}
-void CPUParticles2D::set_pre_process_time(float p_time) {
+void CPUParticles2D::set_pre_process_time(double p_time) {
pre_process_time = p_time;
}
@@ -86,7 +86,7 @@ void CPUParticles2D::set_randomness_ratio(real_t p_ratio) {
randomness_ratio = p_ratio;
}
-void CPUParticles2D::set_lifetime_randomness(float p_random) {
+void CPUParticles2D::set_lifetime_randomness(double p_random) {
lifetime_randomness = p_random;
}
@@ -95,7 +95,7 @@ void CPUParticles2D::set_use_local_coordinates(bool p_enable) {
set_notify_transform(!p_enable);
}
-void CPUParticles2D::set_speed_scale(real_t p_scale) {
+void CPUParticles2D::set_speed_scale(double p_scale) {
speed_scale = p_scale;
}
@@ -107,7 +107,7 @@ int CPUParticles2D::get_amount() const {
return particles.size();
}
-float CPUParticles2D::get_lifetime() const {
+double CPUParticles2D::get_lifetime() const {
return lifetime;
}
@@ -115,7 +115,7 @@ bool CPUParticles2D::get_one_shot() const {
return one_shot;
}
-float CPUParticles2D::get_pre_process_time() const {
+double CPUParticles2D::get_pre_process_time() const {
return pre_process_time;
}
@@ -127,7 +127,7 @@ real_t CPUParticles2D::get_randomness_ratio() const {
return randomness_ratio;
}
-float CPUParticles2D::get_lifetime_randomness() const {
+double CPUParticles2D::get_lifetime_randomness() const {
return lifetime_randomness;
}
@@ -135,7 +135,7 @@ bool CPUParticles2D::get_use_local_coordinates() const {
return local_coords;
}
-real_t CPUParticles2D::get_speed_scale() const {
+double CPUParticles2D::get_speed_scale() const {
return speed_scale;
}
@@ -516,7 +516,7 @@ void CPUParticles2D::_update_internal() {
return;
}
- float delta = get_process_delta_time();
+ double delta = get_process_delta_time();
if (emitting) {
inactive_time = 0;
} else {
@@ -536,14 +536,14 @@ void CPUParticles2D::_update_internal() {
_set_redraw(true);
if (time == 0 && pre_process_time > 0.0) {
- float frame_time;
+ double frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
- float todo = pre_process_time;
+ double todo = pre_process_time;
while (todo >= 0) {
_particles_process(frame_time);
@@ -552,16 +552,16 @@ void CPUParticles2D::_update_internal() {
}
if (fixed_fps > 0) {
- float frame_time = 1.0 / fixed_fps;
- float decr = frame_time;
+ double frame_time = 1.0 / fixed_fps;
+ double decr = frame_time;
- float ldelta = delta;
+ double ldelta = delta;
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
ldelta = 0.1;
} else if (ldelta <= 0.0) { //unlikely but..
ldelta = 0.001;
}
- float todo = frame_remainder + ldelta;
+ double todo = frame_remainder + ldelta;
while (todo >= frame_time) {
_particles_process(frame_time);
@@ -577,7 +577,7 @@ void CPUParticles2D::_update_internal() {
_update_particle_data_buffer();
}
-void CPUParticles2D::_particles_process(float p_delta) {
+void CPUParticles2D::_particles_process(double p_delta) {
p_delta *= speed_scale;
int pcount = particles.size();
@@ -585,7 +585,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
Particle *parray = w;
- float prev_time = time;
+ double prev_time = time;
time += p_delta;
if (time > lifetime) {
time = Math::fmod(time, lifetime);
@@ -604,7 +604,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
velocity_xform[2] = Vector2();
}
- float system_phase = time / lifetime;
+ double system_phase = time / lifetime;
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];
@@ -613,12 +613,12 @@ void CPUParticles2D::_particles_process(float p_delta) {
continue;
}
- float local_delta = p_delta;
+ double local_delta = p_delta;
// The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
// While we use time in tests later on, for randomness we use the phase as done in the
// original shader code, and we later multiply by lifetime to get the time.
- real_t restart_phase = real_t(i) / real_t(pcount);
+ double restart_phase = double(i) / double(pcount);
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
@@ -627,12 +627,12 @@ void CPUParticles2D::_particles_process(float p_delta) {
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
- real_t random = (idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_phase += randomness_ratio * random * 1.0 / pcount;
+ double random = double(idhash(seed) % uint32_t(65536)) / 65536.0;
+ restart_phase += randomness_ratio * random * 1.0 / double(pcount);
}
restart_phase *= (1.0 - explosiveness_ratio);
- float restart_time = restart_phase * lifetime;
+ double restart_time = restart_phase * lifetime;
bool restart = false;
if (time > prev_time) {
@@ -874,7 +874,7 @@ void CPUParticles2D::_particles_process(float p_delta) {
tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
}
- real_t hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
+ real_t hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
real_t hue_rot_c = Math::cos(hue_rot_angle);
real_t hue_rot_s = Math::sin(hue_rot_angle);
diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 92b8be77cf..1a1f35fca5 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -83,7 +83,7 @@ private:
struct Particle {
Transform2D transform;
Color color;
- float custom[4] = {};
+ real_t custom[4] = {};
real_t rotation = 0.0;
Vector2 velocity;
bool active = false;
@@ -91,16 +91,16 @@ private:
real_t scale_rand = 0.0;
real_t hue_rot_rand = 0.0;
real_t anim_offset_rand = 0.0;
- float time = 0.0;
- float lifetime = 0.0;
+ double time = 0.0;
+ double lifetime = 0.0;
Color base_color;
uint32_t seed = 0;
};
- float time = 0.0;
- float inactive_time = 0.0;
- float frame_remainder = 0.0;
+ double time = 0.0;
+ double inactive_time = 0.0;
+ double frame_remainder = 0.0;
int cycle = 0;
bool redraw = false;
@@ -131,12 +131,12 @@ private:
bool one_shot = false;
- float lifetime = 1.0;
- float pre_process_time = 0.0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
real_t explosiveness_ratio = 0.0;
real_t randomness_ratio = 0.0;
- real_t lifetime_randomness = 0.0;
- real_t speed_scale = 1.0;
+ double lifetime_randomness = 0.0;
+ double speed_scale = 1.0;
bool local_coords;
int fixed_fps = 0;
bool fractional_delta = true;
@@ -172,7 +172,7 @@ private:
Vector2 gravity = Vector2(0, 980);
void _update_internal();
- void _particles_process(float p_delta);
+ void _particles_process(double p_delta);
void _update_particle_data_buffer();
Mutex update_mutex;
@@ -193,27 +193,27 @@ protected:
public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
- void set_lifetime(float p_lifetime);
+ void set_lifetime(double p_lifetime);
void set_one_shot(bool p_one_shot);
- void set_pre_process_time(float p_time);
+ void set_pre_process_time(double p_time);
void set_explosiveness_ratio(real_t p_ratio);
void set_randomness_ratio(real_t p_ratio);
- void set_lifetime_randomness(float p_random);
+ void set_lifetime_randomness(double p_random);
void set_visibility_aabb(const Rect2 &p_aabb);
void set_use_local_coordinates(bool p_enable);
- void set_speed_scale(real_t p_scale);
+ void set_speed_scale(double p_scale);
bool is_emitting() const;
int get_amount() const;
- float get_lifetime() const;
+ double get_lifetime() const;
bool get_one_shot() const;
- float get_pre_process_time() const;
+ double get_pre_process_time() const;
real_t get_explosiveness_ratio() const;
real_t get_randomness_ratio() const;
- float get_lifetime_randomness() const;
+ double get_lifetime_randomness() const;
Rect2 get_visibility_aabb() const;
bool get_use_local_coordinates() const;
- real_t get_speed_scale() const;
+ double get_speed_scale() const;
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index adfb94d574..4739d3dd46 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -54,7 +54,7 @@ void GPUParticles2D::set_amount(int p_amount) {
RS::get_singleton()->particles_set_amount(particles, amount);
}
-void GPUParticles2D::set_lifetime(float p_lifetime) {
+void GPUParticles2D::set_lifetime(double p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
RS::get_singleton()->particles_set_lifetime(particles, lifetime);
@@ -76,7 +76,7 @@ void GPUParticles2D::set_one_shot(bool p_enable) {
}
}
-void GPUParticles2D::set_pre_process_time(float p_time) {
+void GPUParticles2D::set_pre_process_time(double p_time) {
pre_process_time = p_time;
RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time);
}
@@ -148,7 +148,8 @@ void GPUParticles2D::set_trail_enabled(bool p_enabled) {
RS::get_singleton()->particles_set_transform_align(particles, p_enabled ? RS::PARTICLES_TRANSFORM_ALIGN_Y_TO_VELOCITY : RS::PARTICLES_TRANSFORM_ALIGN_DISABLED);
}
-void GPUParticles2D::set_trail_length(float p_seconds) {
+
+void GPUParticles2D::set_trail_length(double p_seconds) {
ERR_FAIL_COND(p_seconds < 0.001);
trail_length = p_seconds;
RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
@@ -162,6 +163,7 @@ void GPUParticles2D::set_trail_sections(int p_sections) {
trail_sections = p_sections;
update();
}
+
void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) {
ERR_FAIL_COND(trail_section_subdivisions < 1);
ERR_FAIL_COND(trail_section_subdivisions > 1024);
@@ -173,12 +175,13 @@ void GPUParticles2D::set_trail_section_subdivisions(int p_subdivisions) {
bool GPUParticles2D::is_trail_enabled() const {
return trail_enabled;
}
-float GPUParticles2D::get_trail_length() const {
+
+real_t GPUParticles2D::get_trail_length() const {
return trail_length;
}
void GPUParticles2D::_update_collision_size() {
- float csize = collision_base_size;
+ real_t csize = collision_base_size;
if (texture.is_valid()) {
csize *= (texture->get_width() + texture->get_height()) / 4.0; //half size since its a radius
@@ -187,16 +190,16 @@ void GPUParticles2D::_update_collision_size() {
RS::get_singleton()->particles_set_collision_base_size(particles, csize);
}
-void GPUParticles2D::set_collision_base_size(float p_size) {
+void GPUParticles2D::set_collision_base_size(real_t p_size) {
collision_base_size = p_size;
_update_collision_size();
}
-float GPUParticles2D::get_collision_base_size() const {
+real_t GPUParticles2D::get_collision_base_size() const {
return collision_base_size;
}
-void GPUParticles2D::set_speed_scale(float p_scale) {
+void GPUParticles2D::set_speed_scale(double p_scale) {
speed_scale = p_scale;
RS::get_singleton()->particles_set_speed_scale(particles, p_scale);
}
@@ -209,7 +212,7 @@ int GPUParticles2D::get_amount() const {
return amount;
}
-float GPUParticles2D::get_lifetime() const {
+double GPUParticles2D::get_lifetime() const {
return lifetime;
}
@@ -224,15 +227,15 @@ bool GPUParticles2D::get_one_shot() const {
return one_shot;
}
-float GPUParticles2D::get_pre_process_time() const {
+double GPUParticles2D::get_pre_process_time() const {
return pre_process_time;
}
-float GPUParticles2D::get_explosiveness_ratio() const {
+real_t GPUParticles2D::get_explosiveness_ratio() const {
return explosiveness_ratio;
}
-float GPUParticles2D::get_randomness_ratio() const {
+real_t GPUParticles2D::get_randomness_ratio() const {
return randomness_ratio;
}
@@ -248,7 +251,7 @@ Ref<Material> GPUParticles2D::get_process_material() const {
return process_material;
}
-float GPUParticles2D::get_speed_scale() const {
+double GPUParticles2D::get_speed_scale() const {
return speed_scale;
}
diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h
index 9d8e61daf7..a80e52d60c 100644
--- a/scene/2d/gpu_particles_2d.h
+++ b/scene/2d/gpu_particles_2d.h
@@ -51,11 +51,11 @@ private:
bool one_shot;
int amount;
- float lifetime;
- float pre_process_time;
+ double lifetime;
+ double pre_process_time;
float explosiveness_ratio;
float randomness_ratio;
- float speed_scale;
+ double speed_scale;
Rect2 visibility_rect;
bool local_coords;
int fixed_fps;
@@ -89,36 +89,36 @@ protected:
public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
- void set_lifetime(float p_lifetime);
+ void set_lifetime(double p_lifetime);
void set_one_shot(bool p_enable);
- void set_pre_process_time(float p_time);
+ void set_pre_process_time(double p_time);
void set_explosiveness_ratio(float p_ratio);
void set_randomness_ratio(float p_ratio);
void set_visibility_rect(const Rect2 &p_visibility_rect);
void set_use_local_coordinates(bool p_enable);
void set_process_material(const Ref<Material> &p_material);
- void set_speed_scale(float p_scale);
- void set_collision_base_size(float p_ratio);
+ void set_speed_scale(double p_scale);
+ void set_collision_base_size(real_t p_ratio);
void set_trail_enabled(bool p_enabled);
- void set_trail_length(float p_seconds);
+ void set_trail_length(double p_seconds);
void set_trail_sections(int p_sections);
void set_trail_section_subdivisions(int p_subdivisions);
bool is_emitting() const;
int get_amount() const;
- float get_lifetime() const;
+ double get_lifetime() const;
bool get_one_shot() const;
- float get_pre_process_time() const;
- float get_explosiveness_ratio() const;
- float get_randomness_ratio() const;
+ double get_pre_process_time() const;
+ real_t get_explosiveness_ratio() const;
+ real_t get_randomness_ratio() const;
Rect2 get_visibility_rect() const;
bool get_use_local_coordinates() const;
Ref<Material> get_process_material() const;
- float get_speed_scale() const;
+ double get_speed_scale() const;
- float get_collision_base_size() const;
+ real_t get_collision_base_size() const;
bool is_trail_enabled() const;
- float get_trail_length() const;
+ real_t get_trail_length() const;
int get_trail_sections() const;
int get_trail_section_subdivisions() const;
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index ea639ae3a3..58b20ccad0 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -455,7 +455,7 @@ void NavigationRegion2D::_notification(int p_what) {
// Draw the region
Transform2D xform = get_global_transform();
const NavigationServer2D *ns = NavigationServer2D::get_singleton();
- float radius = ns->map_get_edge_connection_margin(get_world_2d()->get_navigation_map()) / 2.0;
+ real_t radius = ns->map_get_edge_connection_margin(get_world_2d()->get_navigation_map()) / 2.0;
for (int i = 0; i < ns->region_get_connections_count(region); i++) {
// Two main points
Vector2 a = ns->region_get_connection_pathway_start(region, i);
@@ -465,7 +465,7 @@ void NavigationRegion2D::_notification(int p_what) {
draw_line(a, b, doors_color);
// Draw a circle to illustrate the margins.
- float angle = (b - a).angle();
+ real_t angle = (b - a).angle();
draw_arc(a, radius, angle + Math_PI / 2.0, angle - Math_PI / 2.0 + Math_TAU, 10, doors_color);
draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color);
}
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index a382fb2f1e..2d3feb30a1 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -69,7 +69,6 @@ Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_i
}
motion_cache->result = result;
-
return motion_cache;
}
@@ -1046,137 +1045,240 @@ void RigidBody2D::_reload_physics_characteristics() {
//////////////////////////
-//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
+// So, if you pass 45 as limit, avoid numerical precision errors when angle is 45.
#define FLOOR_ANGLE_THRESHOLD 0.01
void CharacterBody2D::move_and_slide() {
- Vector2 body_velocity_normal = linear_velocity.normalized();
- bool was_on_floor = on_floor;
-
- // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky.
float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
- Vector2 current_floor_velocity = floor_velocity;
-
- if ((on_floor || on_wall) && on_floor_body.is_valid()) {
- //this approach makes sure there is less delay between the actual body velocity and the one we saved
- PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(on_floor_body);
- if (bs) {
- current_floor_velocity = bs->get_linear_velocity();
+ Vector2 current_platform_velocity = platform_velocity;
+
+ if ((on_floor || on_wall) && platform_rid.is_valid()) {
+ bool excluded = (exclude_body_layers & platform_layer) != 0;
+ if (!excluded) {
+ // This approach makes sure there is less delay between the actual body velocity and the one we saved.
+ PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid);
+ if (bs) {
+ Transform2D gt = get_global_transform();
+ Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2];
+ current_platform_velocity = bs->get_velocity_at_local_position(local_position);
+ }
+ } else {
+ current_platform_velocity = Vector2();
}
}
motion_results.clear();
+
+ bool was_on_floor = on_floor;
on_floor = false;
on_ceiling = false;
on_wall = false;
- floor_normal = Vector2();
- floor_velocity = Vector2();
- if (current_floor_velocity != Vector2()) {
+ if (!current_platform_velocity.is_equal_approx(Vector2())) {
PhysicsServer2D::MotionResult floor_result;
Set<RID> exclude;
- exclude.insert(on_floor_body);
- if (move_and_collide(current_floor_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
+ exclude.insert(platform_rid);
+ if (move_and_collide(current_platform_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
motion_results.push_back(floor_result);
_set_collision_direction(floor_result);
}
}
- on_floor_body = RID();
Vector2 motion = linear_velocity * delta;
+ Vector2 motion_slide_up = motion.slide(up_direction);
+
+ Vector2 prev_platform_velocity = current_platform_velocity;
+ Vector2 prev_floor_normal = floor_normal;
+ RID prev_platform_rid = platform_rid;
+ int prev_platform_layer = platform_layer;
+
+ platform_rid = RID();
+ floor_normal = Vector2();
+ platform_velocity = Vector2();
// No sliding on first attempt to keep floor motion stable when possible,
- // when stop on slope is enabled.
- bool sliding_enabled = !stop_on_slope;
+ // When stop on slope is enabled or when there is no up direction.
+ bool sliding_enabled = !stop_on_slope || up_direction == Vector2();
+ // Constant speed can be applied only the first time sliding is enabled.
+ bool can_apply_constant_speed = sliding_enabled;
+ bool first_slide = true;
+ bool vel_dir_facing_up = linear_velocity.dot(up_direction) > 0;
+ Vector2 last_travel;
for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer2D::MotionResult result;
bool found_collision = false;
+ Vector2 prev_position = get_global_transform().elements[2];
+
for (int i = 0; i < 2; ++i) {
bool collided;
- if (i == 0) { //collide
+ if (i == 0) { // Collide.
collided = move_and_collide(motion, infinite_inertia, result, margin, true, false, !sliding_enabled);
- if (!collided) {
- motion = Vector2(); //clear because no collision happened and motion completed
- }
- } else { //separate raycasts (if any)
+ } else { // Separate raycasts (if any).
collided = separate_raycast_shapes(result);
if (collided) {
- result.remainder = motion; //keep
+ result.remainder = motion; // Keep.
result.motion = Vector2();
}
}
if (collided) {
found_collision = true;
-
motion_results.push_back(result);
_set_collision_direction(result);
- if (on_floor && stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01) {
- Transform2D gt = get_global_transform();
- if (result.motion.length() > margin) {
- gt.elements[2] -= result.motion.slide(up_direction);
- } else {
+ if (on_floor && stop_on_slope && (linear_velocity.normalized() + up_direction).length() < 0.01) {
+ Transform2D gt = get_global_transform();
+ if (result.motion.length() > margin) {
+ gt.elements[2] -= result.motion.slide(up_direction);
+ } else {
+ gt.elements[2] -= result.motion;
+ }
+ set_global_transform(gt);
+ linear_velocity = Vector2();
+ motion = Vector2();
+ break;
+ }
+
+ if (result.remainder.is_equal_approx(Vector2())) {
+ motion = Vector2();
+ break;
+ }
+
+ // Move on floor only checks.
+ if (move_on_floor_only && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) {
+ // Avoid to move forward on a wall if move_on_floor_only is true.
+ if (was_on_floor && !is_on_floor_only() && !vel_dir_facing_up) {
+ // If the movement is large the body can be prevented from reaching the walls.
+ if (result.motion.length() <= margin) {
+ // Cancels the motion.
+ Transform2D gt = get_global_transform();
gt.elements[2] -= result.motion;
+ set_global_transform(gt);
}
- set_global_transform(gt);
+ on_floor = true;
+ platform_rid = prev_platform_rid;
+ platform_layer = prev_platform_layer;
+
+ platform_velocity = prev_platform_velocity;
+ floor_normal = prev_floor_normal;
linear_velocity = Vector2();
- return;
+ motion = Vector2();
+ break;
+ }
+ // Prevents the body from being able to climb a slope when it moves forward against the wall.
+ else if (!is_on_floor_only()) {
+ motion = up_direction * up_direction.dot(result.remainder);
+ motion = motion.slide(result.collision_normal);
+ } else {
+ motion = result.remainder;
}
}
-
- if (sliding_enabled || !on_floor) {
- motion = result.remainder.slide(result.collision_normal);
- linear_velocity = linear_velocity.slide(result.collision_normal);
- } else {
+ // Constant Speed when the slope is upward.
+ else if (constant_speed_on_floor && is_on_floor_only() && can_apply_constant_speed && was_on_floor && motion.dot(result.collision_normal) < 0) {
+ can_apply_constant_speed = false;
+ Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized();
+ if (!motion_slide_norm.is_equal_approx(Vector2())) {
+ motion = motion_slide_norm * (motion_slide_up.length() - result.motion.slide(up_direction).length() - last_travel.slide(up_direction).length());
+ }
+ }
+ // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling.
+ else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) {
+ Vector2 slide_motion = result.remainder.slide(result.collision_normal);
+ if (slide_motion.dot(linear_velocity) > 0.0) {
+ motion = slide_motion;
+ } else {
+ motion = Vector2();
+ }
+ if (slide_on_ceiling && on_ceiling) {
+ // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall.
+ if (vel_dir_facing_up) {
+ linear_velocity = linear_velocity.slide(result.collision_normal);
+ } else {
+ // Avoid acceleration in slope when falling.
+ linear_velocity = up_direction * up_direction.dot(linear_velocity);
+ }
+ }
+ }
+ // No sliding on first attempt to keep floor motion stable when possible.
+ else {
motion = result.remainder;
+ if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) {
+ linear_velocity = linear_velocity.slide(up_direction);
+ motion = motion.slide(up_direction);
+ }
}
- }
- sliding_enabled = true;
+ last_travel = result.motion;
+ }
+ // When you move forward in a downward slope you don’t collide because you will be in the air.
+ // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied.
+ else if (i == 0 && constant_speed_on_floor && first_slide && _on_floor_if_snapped(was_on_floor, vel_dir_facing_up)) {
+ can_apply_constant_speed = false;
+ sliding_enabled = true;
+ Transform2D gt = get_global_transform();
+ gt.elements[2] = prev_position;
+ set_global_transform(gt);
+
+ Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized();
+ if (!motion_slide_norm.is_equal_approx(Vector2())) {
+ motion = motion_slide_norm * (motion_slide_up.length());
+ found_collision = true;
+ }
+ }
}
+ can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled;
+ sliding_enabled = true;
+ first_slide = false;
- if (!found_collision || motion == Vector2()) {
+ if (!found_collision || motion.is_equal_approx(Vector2())) {
break;
}
}
+ _snap_on_floor(was_on_floor, vel_dir_facing_up);
+
if (!on_floor && !on_wall) {
// Add last platform velocity when just left a moving platform.
- linear_velocity += current_floor_velocity;
+ linear_velocity += current_platform_velocity;
}
- if (!was_on_floor || snap == Vector2()) {
+ // Reset the gravity accumulation when touching the ground.
+ if (on_floor && !vel_dir_facing_up) {
+ linear_velocity = linear_velocity.slide(up_direction);
+ }
+}
+
+void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up) {
+ if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) {
return;
}
- // Apply snap.
Transform2D gt = get_global_transform();
PhysicsServer2D::MotionResult result;
- if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) {
+ if (move_and_collide(up_direction * -floor_snap_length, infinite_inertia, result, margin, false, true, false)) {
bool apply = true;
- if (up_direction != Vector2()) {
- if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
- on_floor = true;
- floor_normal = result.collision_normal;
- on_floor_body = result.collider;
- floor_velocity = result.collider_velocity;
- if (stop_on_slope) {
- // move and collide may stray the object a bit because of pre un-stucking,
- // so only ensure that motion happens on floor direction in this case.
- if (result.motion.length() > margin) {
- result.motion = up_direction * up_direction.dot(result.motion);
- } else {
- result.motion = Vector2();
- }
+ float collision_angle = Math::acos(result.collision_normal.dot(up_direction));
+ if (collision_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ on_floor = true;
+ floor_normal = result.collision_normal;
+ platform_velocity = result.collider_velocity;
+ _set_platform_data(result);
+
+ if (stop_on_slope) {
+ // move and collide may stray the object a bit because of pre un-stucking,
+ // so only ensure that motion happens on floor direction in this case.
+ if (result.motion.length() > margin) {
+ result.motion = up_direction * up_direction.dot(result.motion);
+ } else {
+ result.motion = Vector2();
}
- } else {
- apply = false;
}
+ } else {
+ apply = false;
}
if (apply) {
@@ -1186,23 +1288,46 @@ void CharacterBody2D::move_and_slide() {
}
}
+bool CharacterBody2D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facing_up) {
+ if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) {
+ return false;
+ }
+
+ PhysicsServer2D::MotionResult result;
+ if (move_and_collide(up_direction * -floor_snap_length, infinite_inertia, result, margin, false, true, false)) {
+ if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
if (up_direction == Vector2()) {
- //all is a wall
- on_wall = true;
+ return;
+ }
+
+ if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ on_floor = true;
+ floor_normal = p_result.collision_normal;
+ platform_velocity = p_result.collider_velocity;
+ _set_platform_data(p_result);
+ } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ on_ceiling = true;
} else {
- if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
- on_floor = true;
- floor_normal = p_result.collision_normal;
- on_floor_body = p_result.collider;
- floor_velocity = p_result.collider_velocity;
- } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
- on_ceiling = true;
- } else {
- on_wall = true;
- on_floor_body = p_result.collider;
- floor_velocity = p_result.collider_velocity;
- }
+ on_wall = true;
+ platform_velocity = p_result.collider_velocity;
+ _set_platform_data(p_result);
+ }
+}
+
+void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) {
+ platform_rid = p_result.collider;
+ platform_layer = 0;
+ CollisionObject2D *collision_object = Object::cast_to<CollisionObject2D>(ObjectDB::get_instance(p_result.collider_id));
+ if (collision_object) {
+ platform_layer = collision_object->get_collision_layer();
}
}
@@ -1254,20 +1379,32 @@ bool CharacterBody2D::is_on_floor() const {
return on_floor;
}
+bool CharacterBody2D::is_on_floor_only() const {
+ return on_floor && !on_wall && !on_ceiling;
+}
+
bool CharacterBody2D::is_on_wall() const {
return on_wall;
}
+bool CharacterBody2D::is_on_wall_only() const {
+ return on_wall && !on_floor && !on_ceiling;
+}
+
bool CharacterBody2D::is_on_ceiling() const {
return on_ceiling;
}
+bool CharacterBody2D::is_on_ceiling_only() const {
+ return on_ceiling && !on_floor && !on_wall;
+}
+
Vector2 CharacterBody2D::get_floor_normal() const {
return floor_normal;
}
-Vector2 CharacterBody2D::get_floor_velocity() const {
- return floor_velocity;
+Vector2 CharacterBody2D::get_platform_velocity() const {
+ return platform_velocity;
}
int CharacterBody2D::get_slide_count() const {
@@ -1317,6 +1454,35 @@ void CharacterBody2D::set_infinite_inertia_enabled(bool p_enabled) {
infinite_inertia = p_enabled;
}
+bool CharacterBody2D::is_constant_speed_on_floor_enabled() const {
+ return constant_speed_on_floor;
+}
+void CharacterBody2D::set_constant_speed_on_floor_enabled(bool p_enabled) {
+ constant_speed_on_floor = p_enabled;
+}
+
+bool CharacterBody2D::is_move_on_floor_only_enabled() const {
+ return move_on_floor_only;
+}
+void CharacterBody2D::set_move_on_floor_only_enabled(bool p_enabled) {
+ move_on_floor_only = p_enabled;
+}
+
+bool CharacterBody2D::is_slide_on_ceiling_enabled() const {
+ return slide_on_ceiling;
+}
+void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) {
+ slide_on_ceiling = p_enabled;
+}
+
+uint32_t CharacterBody2D::get_exclude_body_layers() const {
+ return exclude_body_layers;
+}
+
+void CharacterBody2D::set_exclude_body_layers(uint32_t p_exclude_layers) {
+ exclude_body_layers = p_exclude_layers;
+}
+
int CharacterBody2D::get_max_slides() const {
return max_slides;
}
@@ -1334,12 +1500,13 @@ void CharacterBody2D::set_floor_max_angle(real_t p_radians) {
floor_max_angle = p_radians;
}
-const Vector2 &CharacterBody2D::get_snap() const {
- return snap;
+real_t CharacterBody2D::get_floor_snap_length() {
+ return floor_snap_length;
}
-void CharacterBody2D::set_snap(const Vector2 &p_snap) {
- snap = p_snap;
+void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) {
+ ERR_FAIL_COND(p_floor_snap_length < 0);
+ floor_snap_length = p_floor_snap_length;
}
const Vector2 &CharacterBody2D::get_up_direction() const {
@@ -1355,11 +1522,11 @@ void CharacterBody2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
// Reset move_and_slide() data.
on_floor = false;
- on_floor_body = RID();
+ platform_rid = RID();
on_ceiling = false;
on_wall = false;
motion_results.clear();
- floor_velocity = Vector2();
+ platform_velocity = Vector2();
} break;
}
}
@@ -1375,31 +1542,48 @@ void CharacterBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_stop_on_slope_enabled"), &CharacterBody2D::is_stop_on_slope_enabled);
ClassDB::bind_method(D_METHOD("set_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_stop_on_slope_enabled);
ClassDB::bind_method(D_METHOD("is_infinite_inertia_enabled"), &CharacterBody2D::is_infinite_inertia_enabled);
+ ClassDB::bind_method(D_METHOD("set_constant_speed_on_floor_enabled", "enabled"), &CharacterBody2D::set_constant_speed_on_floor_enabled);
+ ClassDB::bind_method(D_METHOD("is_constant_speed_on_floor_enabled"), &CharacterBody2D::is_constant_speed_on_floor_enabled);
+ ClassDB::bind_method(D_METHOD("set_move_on_floor_only_enabled", "enabled"), &CharacterBody2D::set_move_on_floor_only_enabled);
+ ClassDB::bind_method(D_METHOD("is_move_on_floor_only_enabled"), &CharacterBody2D::is_move_on_floor_only_enabled);
+ ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled);
+ ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_exclude_body_layers", "exclude_layer"), &CharacterBody2D::set_exclude_body_layers);
+ ClassDB::bind_method(D_METHOD("get_exclude_body_layers"), &CharacterBody2D::get_exclude_body_layers);
+
ClassDB::bind_method(D_METHOD("set_infinite_inertia_enabled", "enabled"), &CharacterBody2D::set_infinite_inertia_enabled);
ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides);
ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides);
ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle);
ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle);
- ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap);
- ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap);
+ ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length);
+ ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length);
ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction);
ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction);
ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor);
+ ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling);
+ ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only);
ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall);
+ ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only);
ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal);
- ClassDB::bind_method(D_METHOD("get_floor_velocity"), &CharacterBody2D::get_floor_velocity);
+ ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity);
ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "constant_speed_on_floor"), "set_constant_speed_on_floor_enabled", "is_constant_speed_on_floor_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "move_on_floor_only"), "set_move_on_floor_only_enabled", "is_move_on_floor_only_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_RANGE, "1,8,1,or_greater"), "set_max_slides", "get_max_slides");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_floor_max_angle", "get_floor_max_angle");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1000,0.1"), "set_floor_snap_length", "get_floor_snap_length");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "exclude_body_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_exclude_body_layers", "get_exclude_body_layers");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 7a319aabc9..00948b4344 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -273,16 +273,20 @@ private:
bool stop_on_slope = false;
bool infinite_inertia = true;
+ bool constant_speed_on_floor = false;
+ bool move_on_floor_only = true;
+ bool slide_on_ceiling = true;
int max_slides = 4;
+ int platform_layer;
real_t floor_max_angle = Math::deg2rad((real_t)45.0);
- Vector2 snap;
+ float floor_snap_length = 0;
Vector2 up_direction = Vector2(0.0, -1.0);
-
+ uint32_t exclude_body_layers = 0;
Vector2 linear_velocity;
Vector2 floor_normal;
- Vector2 floor_velocity;
- RID on_floor_body;
+ Vector2 platform_velocity;
+ RID platform_rid;
bool on_floor = false;
bool on_ceiling = false;
bool on_wall = false;
@@ -290,8 +294,6 @@ private:
Vector<PhysicsServer2D::MotionResult> motion_results;
Vector<Ref<KinematicCollision2D>> slide_colliders;
- Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
-
bool separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result);
void set_safe_margin(real_t p_margin);
@@ -303,18 +305,37 @@ private:
bool is_infinite_inertia_enabled() const;
void set_infinite_inertia_enabled(bool p_enabled);
+ bool is_constant_speed_on_floor_enabled() const;
+ void set_constant_speed_on_floor_enabled(bool p_enabled);
+
+ bool is_move_on_floor_only_enabled() const;
+ void set_move_on_floor_only_enabled(bool p_enabled);
+
+ bool is_slide_on_ceiling_enabled() const;
+ void set_slide_on_ceiling_enabled(bool p_enabled);
+
int get_max_slides() const;
void set_max_slides(int p_max_slides);
+ real_t get_move_max_angle() const;
+ void set_move_max_angle(real_t p_radians);
+
real_t get_floor_max_angle() const;
void set_floor_max_angle(real_t p_radians);
- const Vector2 &get_snap() const;
- void set_snap(const Vector2 &p_snap);
+ real_t get_floor_snap_length();
+ void set_floor_snap_length(real_t p_floor_snap_length);
+ uint32_t get_exclude_body_layers() const;
+ void set_exclude_body_layers(const uint32_t p_exclude_layer);
+
+ Ref<KinematicCollision2D> _get_slide_collision(int p_bounce);
const Vector2 &get_up_direction() const;
+ bool _on_floor_if_snapped(bool was_on_floor, bool vel_dir_facing_up);
void set_up_direction(const Vector2 &p_up_direction);
void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result);
+ void _set_platform_data(const PhysicsServer2D::MotionResult &p_result);
+ void _snap_on_floor(bool was_on_floor, bool vel_dir_facing_up);
protected:
void _notification(int p_what);
@@ -327,10 +348,13 @@ public:
void set_linear_velocity(const Vector2 &p_velocity);
bool is_on_floor() const;
+ bool is_on_floor_only() const;
bool is_on_wall() const;
+ bool is_on_wall_only() const;
bool is_on_ceiling() const;
+ bool is_on_ceiling_only() const;
Vector2 get_floor_normal() const;
- Vector2 get_floor_velocity() const;
+ Vector2 get_platform_velocity() const;
int get_slide_count() const;
PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index f6740040c1..602a0f2115 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -212,17 +212,17 @@ void RayCast2D::_update_raycast_state() {
void RayCast2D::_draw_debug_shape() {
Color draw_col = collided ? Color(1.0, 0.01, 0) : get_tree()->get_debug_collisions_color();
if (!enabled) {
- float g = draw_col.get_v();
+ const float g = draw_col.get_v();
draw_col.r = g;
draw_col.g = g;
draw_col.b = g;
}
// Draw an arrow indicating where the RayCast is pointing to
- const float max_arrow_size = 6;
- const float line_width = 1.4;
+ const real_t max_arrow_size = 6;
+ const real_t line_width = 1.4;
bool no_line = target_position.length() < line_width;
- float arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
+ real_t arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
if (no_line) {
arrow_size = target_position.length();
diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 15cbdf535e..85d632af00 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -45,7 +45,7 @@ bool Bone2D::_set(const StringName &p_path, const Variant &p_value) {
} else if (path.begins_with("length")) {
set_length(p_value);
} else if (path.begins_with("bone_angle")) {
- set_bone_angle(Math::deg2rad(float(p_value)));
+ set_bone_angle(Math::deg2rad(real_t(p_value)));
} else if (path.begins_with("default_length")) {
set_length(p_value);
}
@@ -330,7 +330,7 @@ bool Bone2D::_editor_get_bone_shape(Vector<Vector2> *p_shape, Vector<Vector2> *p
rel = (p_other_bone->get_global_transform().get_origin() - get_global_transform().get_origin());
rel = rel.rotated(-get_global_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
} else {
- float angle_to_use = get_rotation() + bone_angle;
+ real_t angle_to_use = get_rotation() + bone_angle;
rel = Vector2(cos(angle_to_use), sin(angle_to_use)) * (length * MIN(get_global_scale().x, get_global_scale().y));
rel = rel.rotated(-get_rotation()); // Undo Bone2D node's rotation so its drawn correctly regardless of the node's rotation
}
@@ -414,12 +414,12 @@ void Bone2D::apply_rest() {
set_transform(rest);
}
-void Bone2D::set_default_length(float p_length) {
+void Bone2D::set_default_length(real_t p_length) {
WARN_DEPRECATED_MSG("set_default_length is deprecated. Please use set_length instead!");
set_length(p_length);
}
-float Bone2D::get_default_length() const {
+real_t Bone2D::get_default_length() const {
WARN_DEPRECATED_MSG("get_default_length is deprecated. Please use get_length instead!");
return get_length();
}
@@ -485,7 +485,7 @@ bool Bone2D::get_autocalculate_length_and_angle() const {
return autocalculate_length_and_angle;
}
-void Bone2D::set_length(float p_length) {
+void Bone2D::set_length(real_t p_length) {
length = p_length;
#ifdef TOOLS_ENABLED
@@ -493,11 +493,11 @@ void Bone2D::set_length(float p_length) {
#endif // TOOLS_ENABLED
}
-float Bone2D::get_length() const {
+real_t Bone2D::get_length() const {
return length;
}
-void Bone2D::set_bone_angle(float p_angle) {
+void Bone2D::set_bone_angle(real_t p_angle) {
bone_angle = p_angle;
#ifdef TOOLS_ENABLED
@@ -505,7 +505,7 @@ void Bone2D::set_bone_angle(float p_angle) {
#endif // TOOLS_ENABLED
}
-float Bone2D::get_bone_angle() const {
+real_t Bone2D::get_bone_angle() const {
return bone_angle;
}
@@ -690,7 +690,7 @@ RID Skeleton2D::get_skeleton() const {
return skeleton;
}
-void Skeleton2D::set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, float p_amount, bool p_persistent) {
+void Skeleton2D::set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, real_t p_amount, bool p_persistent) {
ERR_FAIL_INDEX_MSG(p_bone_idx, bones.size(), "Bone index is out of range!");
bones.write[p_bone_idx].local_pose_override = p_override;
bones.write[p_bone_idx].local_pose_override_amount = p_amount;
@@ -728,7 +728,7 @@ Ref<SkeletonModificationStack2D> Skeleton2D::get_modification_stack() const {
return modification_stack;
}
-void Skeleton2D::execute_modifications(float p_delta, int p_execution_mode) {
+void Skeleton2D::execute_modifications(real_t p_delta, int p_execution_mode) {
if (!modification_stack.is_valid()) {
return;
}
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index 59bd711960..56fd0e8504 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -49,8 +49,8 @@ class Bone2D : public Node2D {
Transform2D rest;
bool autocalculate_length_and_angle = true;
- float length = 16;
- float bone_angle = 0;
+ real_t length = 16;
+ real_t bone_angle = 0;
int skeleton_index = -1;
@@ -85,10 +85,10 @@ public:
void set_autocalculate_length_and_angle(bool p_autocalculate);
bool get_autocalculate_length_and_angle() const;
- void set_length(float p_length);
- float get_length() const;
- void set_bone_angle(float p_angle);
- float get_bone_angle() const;
+ void set_length(real_t p_length);
+ real_t get_length() const;
+ void set_bone_angle(real_t p_angle);
+ real_t get_bone_angle() const;
int get_index_in_skeleton() const;
@@ -122,7 +122,7 @@ class Skeleton2D : public Node2D {
//Transform2D local_pose_cache;
Transform2D local_pose_override;
- float local_pose_override_amount = 0;
+ real_t local_pose_override_amount = 0;
bool local_pose_override_persistent = false;
};
@@ -153,12 +153,12 @@ public:
RID get_skeleton() const;
- void set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, float p_amount, bool p_persistent = true);
+ void set_bone_local_pose_override(int p_bone_idx, Transform2D p_override, real_t p_amount, bool p_persistent = true);
Transform2D get_bone_local_pose_override(int p_bone_idx);
Ref<SkeletonModificationStack2D> get_modification_stack() const;
void set_modification_stack(Ref<SkeletonModificationStack2D> p_stack);
- void execute_modifications(float p_delta, int p_execution_mode);
+ void execute_modifications(real_t p_delta, int p_execution_mode);
Skeleton2D();
~Skeleton2D();
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index bb8f9f8ccb..6318aad08e 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -407,14 +407,14 @@ void AudioStreamPlayer3D::_notification(int p_what) {
for (const Set<Camera3D *>::Element *E = world_3d->get_cameras().front(); E; E = E->next()) {
Camera3D *camera = E->get();
Viewport *vp = camera->get_viewport();
- if (!vp->is_audio_listener()) {
+ if (!vp->is_audio_listener_3d()) {
continue;
}
bool listener_is_camera = true;
Node3D *listener_node = camera;
- Listener3D *listener = vp->get_listener();
+ Listener3D *listener = vp->get_listener_3d();
if (listener) {
listener_node = listener;
listener_is_camera = false;
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 2e962b96c3..e504277a55 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -153,7 +153,7 @@ Transform3D Camera3D::get_camera_transform() const {
return tr;
}
-void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
+void Camera3D::set_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far) {
if (!force_change && fov == p_fovy_degrees && p_z_near == near && p_z_far == far && mode == PROJECTION_PERSPECTIVE) {
return;
}
@@ -168,7 +168,7 @@ void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_f
force_change = false;
}
-void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
+void Camera3D::set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far) {
if (!force_change && size == p_size && p_z_near == near && p_z_far == far && mode == PROJECTION_ORTHOGONAL) {
return;
}
@@ -184,7 +184,7 @@ void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
update_gizmos();
}
-void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
+void Camera3D::set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far) {
if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM) {
return;
}
@@ -295,7 +295,7 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const {
return get_camera_transform().origin;
} else {
Vector2 pos = cpos / viewport_size;
- float vsize, hsize;
+ real_t vsize, hsize;
if (keep_aspect == KEEP_WIDTH) {
vsize = size / viewport_size.aspect();
hsize = size;
@@ -368,7 +368,7 @@ Point2 Camera3D::unproject_position(const Vector3 &p_pos) const {
return res;
}
-Vector3 Camera3D::project_position(const Point2 &p_point, float p_z_depth) const {
+Vector3 Camera3D::project_position(const Point2 &p_point, real_t p_z_depth) const {
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene.");
if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) {
@@ -531,15 +531,15 @@ void Camera3D::_bind_methods() {
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);
}
-float Camera3D::get_fov() const {
+real_t Camera3D::get_fov() const {
return fov;
}
-float Camera3D::get_size() const {
+real_t Camera3D::get_size() const {
return size;
}
-float Camera3D::get_near() const {
+real_t Camera3D::get_near() const {
return near;
}
@@ -547,7 +547,7 @@ Vector2 Camera3D::get_frustum_offset() const {
return frustum_offset;
}
-float Camera3D::get_far() const {
+real_t Camera3D::get_far() const {
return far;
}
@@ -555,19 +555,19 @@ Camera3D::Projection Camera3D::get_projection() const {
return mode;
}
-void Camera3D::set_fov(float p_fov) {
+void Camera3D::set_fov(real_t p_fov) {
ERR_FAIL_COND(p_fov < 1 || p_fov > 179);
fov = p_fov;
_update_camera_mode();
}
-void Camera3D::set_size(float p_size) {
+void Camera3D::set_size(real_t p_size) {
ERR_FAIL_COND(p_size < 0.1 || p_size > 16384);
size = p_size;
_update_camera_mode();
}
-void Camera3D::set_near(float p_near) {
+void Camera3D::set_near(real_t p_near) {
near = p_near;
_update_camera_mode();
}
@@ -577,7 +577,7 @@ void Camera3D::set_frustum_offset(Vector2 p_offset) {
_update_camera_mode();
}
-void Camera3D::set_far(float p_far) {
+void Camera3D::set_far(real_t p_far) {
far = p_far;
_update_camera_mode();
}
@@ -630,21 +630,21 @@ bool Camera3D::is_position_in_frustum(const Vector3 &p_position) const {
return true;
}
-void Camera3D::set_v_offset(float p_offset) {
+void Camera3D::set_v_offset(real_t p_offset) {
v_offset = p_offset;
_update_camera();
}
-float Camera3D::get_v_offset() const {
+real_t Camera3D::get_v_offset() const {
return v_offset;
}
-void Camera3D::set_h_offset(float p_offset) {
+void Camera3D::set_h_offset(real_t p_offset) {
h_offset = p_offset;
_update_camera();
}
-float Camera3D::get_h_offset() const {
+real_t Camera3D::get_h_offset() const {
return h_offset;
}
@@ -672,11 +672,11 @@ Camera3D::~Camera3D() {
////////////////////////////////////////
-void ClippedCamera3D::set_margin(float p_margin) {
+void ClippedCamera3D::set_margin(real_t p_margin) {
margin = p_margin;
}
-float ClippedCamera3D::get_margin() const {
+real_t ClippedCamera3D::get_margin() const {
return margin;
}
@@ -746,7 +746,7 @@ void ClippedCamera3D::_notification(int p_what) {
xf.origin = ray_from;
xf.orthonormalize();
- float closest_safe = 1.0f, closest_unsafe = 1.0f;
+ real_t closest_safe = 1.0f, closest_unsafe = 1.0f;
if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, closest_safe, closest_unsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) {
clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * closest_safe);
}
@@ -813,7 +813,7 @@ void ClippedCamera3D::clear_exceptions() {
exclude.clear();
}
-float ClippedCamera3D::get_clip_offset() const {
+real_t ClippedCamera3D::get_clip_offset() const {
return clip_offset;
}
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index c6efc8f9a9..61e3f51d0b 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -63,13 +63,13 @@ private:
Projection mode = PROJECTION_PERSPECTIVE;
- float fov = 0.0;
- float size = 1.0;
+ real_t fov = 0.0;
+ real_t size = 1.0;
Vector2 frustum_offset;
- float near = 0.0;
- float far = 0.0;
- float v_offset = 0.0;
- float h_offset = 0.0;
+ real_t near = 0.0;
+ real_t far = 0.0;
+ real_t v_offset = 0.0;
+ real_t h_offset = 0.0;
KeepAspect keep_aspect = KEEP_HEIGHT;
RID camera;
@@ -107,10 +107,9 @@ public:
NOTIFICATION_LOST_CURRENT = 51
};
- void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
- void set_orthogonal(float p_size, float p_z_near, float p_z_far);
- void set_frustum(float p_size, Vector2 p_offset, float p_z_near,
- float p_z_far);
+ void set_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
+ void set_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
+ void set_frustum(real_t p_size, Vector2 p_offset, real_t p_z_near, real_t p_z_far);
void set_projection(Camera3D::Projection p_mode);
void make_current();
@@ -120,18 +119,18 @@ public:
RID get_camera() const;
- float get_fov() const;
- float get_size() const;
- float get_far() const;
- float get_near() const;
+ real_t get_fov() const;
+ real_t get_size() const;
+ real_t get_far() const;
+ real_t get_near() const;
Vector2 get_frustum_offset() const;
Projection get_projection() const;
- void set_fov(float p_fov);
- void set_size(float p_size);
- void set_far(float p_far);
- void set_near(float p_near);
+ void set_fov(real_t p_fov);
+ void set_size(real_t p_size);
+ void set_far(real_t p_far);
+ void set_near(real_t p_near);
void set_frustum_offset(Vector2 p_offset);
virtual Transform3D get_camera_transform() const;
@@ -141,8 +140,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const;
virtual Point2 unproject_position(const Vector3 &p_pos) const;
bool is_position_behind(const Vector3 &p_pos) const;
- virtual Vector3 project_position(const Point2 &p_point,
- float p_z_depth) const;
+ virtual Vector3 project_position(const Point2 &p_point, real_t p_z_depth) const;
Vector<Vector3> get_near_plane_points() const;
@@ -164,11 +162,11 @@ public:
void set_keep_aspect_mode(KeepAspect p_aspect);
KeepAspect get_keep_aspect_mode() const;
- void set_v_offset(float p_offset);
- float get_v_offset() const;
+ void set_v_offset(real_t p_offset);
+ real_t get_v_offset() const;
- void set_h_offset(float p_offset);
- float get_h_offset() const;
+ void set_h_offset(real_t p_offset);
+ real_t get_h_offset() const;
void set_doppler_tracking(DopplerTracking p_tracking);
DopplerTracking get_doppler_tracking() const;
@@ -195,8 +193,8 @@ public:
private:
ClipProcessCallback process_callback = CLIP_PROCESS_PHYSICS;
RID pyramid_shape;
- float margin = 0.0;
- float clip_offset = 0.0;
+ real_t margin = 0.0;
+ real_t clip_offset = 0.0;
uint32_t collision_mask = 1;
bool clip_to_areas = false;
bool clip_to_bodies = true;
@@ -217,8 +215,8 @@ public:
void set_clip_to_bodies(bool p_clip);
bool is_clip_to_bodies_enabled() const;
- void set_margin(float p_margin);
- float get_margin() const;
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
void set_process_callback(ClipProcessCallback p_mode);
ClipProcessCallback get_process_callback() const;
@@ -235,7 +233,7 @@ public:
void remove_exception(const Object *p_object);
void clear_exceptions();
- float get_clip_offset() const;
+ real_t get_clip_offset() const;
ClippedCamera3D();
~ClippedCamera3D();
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 60f8ad8f36..2377c618aa 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -78,7 +78,7 @@ void CPUParticles3D::set_amount(int p_amount) {
particle_order.resize(p_amount);
}
-void CPUParticles3D::set_lifetime(float p_lifetime) {
+void CPUParticles3D::set_lifetime(double p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
}
@@ -87,19 +87,19 @@ void CPUParticles3D::set_one_shot(bool p_one_shot) {
one_shot = p_one_shot;
}
-void CPUParticles3D::set_pre_process_time(float p_time) {
+void CPUParticles3D::set_pre_process_time(double p_time) {
pre_process_time = p_time;
}
-void CPUParticles3D::set_explosiveness_ratio(float p_ratio) {
+void CPUParticles3D::set_explosiveness_ratio(real_t p_ratio) {
explosiveness_ratio = p_ratio;
}
-void CPUParticles3D::set_randomness_ratio(float p_ratio) {
+void CPUParticles3D::set_randomness_ratio(real_t p_ratio) {
randomness_ratio = p_ratio;
}
-void CPUParticles3D::set_lifetime_randomness(float p_random) {
+void CPUParticles3D::set_lifetime_randomness(double p_random) {
lifetime_randomness = p_random;
}
@@ -107,7 +107,7 @@ void CPUParticles3D::set_use_local_coordinates(bool p_enable) {
local_coords = p_enable;
}
-void CPUParticles3D::set_speed_scale(float p_scale) {
+void CPUParticles3D::set_speed_scale(double p_scale) {
speed_scale = p_scale;
}
@@ -119,7 +119,7 @@ int CPUParticles3D::get_amount() const {
return particles.size();
}
-float CPUParticles3D::get_lifetime() const {
+double CPUParticles3D::get_lifetime() const {
return lifetime;
}
@@ -127,19 +127,19 @@ bool CPUParticles3D::get_one_shot() const {
return one_shot;
}
-float CPUParticles3D::get_pre_process_time() const {
+double CPUParticles3D::get_pre_process_time() const {
return pre_process_time;
}
-float CPUParticles3D::get_explosiveness_ratio() const {
+real_t CPUParticles3D::get_explosiveness_ratio() const {
return explosiveness_ratio;
}
-float CPUParticles3D::get_randomness_ratio() const {
+real_t CPUParticles3D::get_randomness_ratio() const {
return randomness_ratio;
}
-float CPUParticles3D::get_lifetime_randomness() const {
+double CPUParticles3D::get_lifetime_randomness() const {
return lifetime_randomness;
}
@@ -147,7 +147,7 @@ bool CPUParticles3D::get_use_local_coordinates() const {
return local_coords;
}
-float CPUParticles3D::get_speed_scale() const {
+double CPUParticles3D::get_speed_scale() const {
return speed_scale;
}
@@ -247,47 +247,47 @@ Vector3 CPUParticles3D::get_direction() const {
return direction;
}
-void CPUParticles3D::set_spread(float p_spread) {
+void CPUParticles3D::set_spread(real_t p_spread) {
spread = p_spread;
}
-float CPUParticles3D::get_spread() const {
+real_t CPUParticles3D::get_spread() const {
return spread;
}
-void CPUParticles3D::set_flatness(float p_flatness) {
+void CPUParticles3D::set_flatness(real_t p_flatness) {
flatness = p_flatness;
}
-float CPUParticles3D::get_flatness() const {
+real_t CPUParticles3D::get_flatness() const {
return flatness;
}
-void CPUParticles3D::set_param(Parameter p_param, float p_value) {
+void CPUParticles3D::set_param(Parameter p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
parameters[p_param] = p_value;
}
-float CPUParticles3D::get_param(Parameter p_param) const {
+real_t CPUParticles3D::get_param(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return parameters[p_param];
}
-void CPUParticles3D::set_param_randomness(Parameter p_param, float p_value) {
+void CPUParticles3D::set_param_randomness(Parameter p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
randomness[p_param] = p_value;
}
-float CPUParticles3D::get_param_randomness(Parameter p_param) const {
+real_t CPUParticles3D::get_param_randomness(Parameter p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return randomness[p_param];
}
-static void _adjust_curve_range(const Ref<Curve> &p_curve, float p_min, float p_max) {
+static void _adjust_curve_range(const Ref<Curve> &p_curve, real_t p_min, real_t p_max) {
Ref<Curve> curve = p_curve;
if (!curve.is_valid()) {
return;
@@ -381,7 +381,7 @@ void CPUParticles3D::set_emission_shape(EmissionShape p_shape) {
emission_shape = p_shape;
}
-void CPUParticles3D::set_emission_sphere_radius(float p_radius) {
+void CPUParticles3D::set_emission_sphere_radius(real_t p_radius) {
emission_sphere_radius = p_radius;
}
@@ -405,19 +405,19 @@ void CPUParticles3D::set_emission_ring_axis(Vector3 p_axis) {
emission_ring_axis = p_axis;
}
-void CPUParticles3D::set_emission_ring_height(float p_height) {
+void CPUParticles3D::set_emission_ring_height(real_t p_height) {
emission_ring_height = p_height;
}
-void CPUParticles3D::set_emission_ring_radius(float p_radius) {
+void CPUParticles3D::set_emission_ring_radius(real_t p_radius) {
emission_ring_radius = p_radius;
}
-void CPUParticles3D::set_emission_ring_inner_radius(float p_radius) {
+void CPUParticles3D::set_emission_ring_inner_radius(real_t p_radius) {
emission_ring_inner_radius = p_radius;
}
-float CPUParticles3D::get_emission_sphere_radius() const {
+real_t CPUParticles3D::get_emission_sphere_radius() const {
return emission_sphere_radius;
}
@@ -441,15 +441,15 @@ Vector3 CPUParticles3D::get_emission_ring_axis() const {
return emission_ring_axis;
}
-float CPUParticles3D::get_emission_ring_height() const {
+real_t CPUParticles3D::get_emission_ring_height() const {
return emission_ring_height;
}
-float CPUParticles3D::get_emission_ring_radius() const {
+real_t CPUParticles3D::get_emission_ring_radius() const {
return emission_ring_radius;
}
-float CPUParticles3D::get_emission_ring_inner_radius() const {
+real_t CPUParticles3D::get_emission_ring_inner_radius() const {
return emission_ring_inner_radius;
}
@@ -498,7 +498,7 @@ static uint32_t idhash(uint32_t x) {
return x;
}
-static float rand_from_seed(uint32_t &seed) {
+static real_t rand_from_seed(uint32_t &seed) {
int k;
int s = int(seed);
if (s == 0) {
@@ -510,7 +510,7 @@ static float rand_from_seed(uint32_t &seed) {
s += 2147483647;
}
seed = uint32_t(s);
- return float(seed % uint32_t(65536)) / 65535.0;
+ return (seed % uint32_t(65536)) / 65535.0;
}
void CPUParticles3D::_update_internal() {
@@ -519,7 +519,7 @@ void CPUParticles3D::_update_internal() {
return;
}
- float delta = get_process_delta_time();
+ double delta = get_process_delta_time();
if (emitting) {
inactive_time = 0;
} else {
@@ -541,14 +541,14 @@ void CPUParticles3D::_update_internal() {
bool processed = false;
if (time == 0 && pre_process_time > 0.0) {
- float frame_time;
+ double frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
- float todo = pre_process_time;
+ double todo = pre_process_time;
while (todo >= 0) {
_particles_process(frame_time);
@@ -558,16 +558,16 @@ void CPUParticles3D::_update_internal() {
}
if (fixed_fps > 0) {
- float frame_time = 1.0 / fixed_fps;
- float decr = frame_time;
+ double frame_time = 1.0 / fixed_fps;
+ double decr = frame_time;
- float ldelta = delta;
+ double ldelta = delta;
if (ldelta > 0.1) { //avoid recursive stalls if fps goes below 10
ldelta = 0.1;
} else if (ldelta <= 0.0) { //unlikely but..
ldelta = 0.001;
}
- float todo = frame_remainder + ldelta;
+ double todo = frame_remainder + ldelta;
while (todo >= frame_time) {
_particles_process(frame_time);
@@ -587,7 +587,7 @@ void CPUParticles3D::_update_internal() {
}
}
-void CPUParticles3D::_particles_process(float p_delta) {
+void CPUParticles3D::_particles_process(double p_delta) {
p_delta *= speed_scale;
int pcount = particles.size();
@@ -595,7 +595,7 @@ void CPUParticles3D::_particles_process(float p_delta) {
Particle *parray = w;
- float prev_time = time;
+ double prev_time = time;
time += p_delta;
if (time > lifetime) {
time = Math::fmod(time, lifetime);
@@ -613,7 +613,7 @@ void CPUParticles3D::_particles_process(float p_delta) {
velocity_xform = emission_xform.basis;
}
- float system_phase = time / lifetime;
+ double system_phase = time / lifetime;
for (int i = 0; i < pcount; i++) {
Particle &p = parray[i];
@@ -622,12 +622,12 @@ void CPUParticles3D::_particles_process(float p_delta) {
continue;
}
- float local_delta = p_delta;
+ double local_delta = p_delta;
// The phase is a ratio between 0 (birth) and 1 (end of life) for each particle.
// While we use time in tests later on, for randomness we use the phase as done in the
// original shader code, and we later multiply by lifetime to get the time.
- float restart_phase = float(i) / float(pcount);
+ double restart_phase = double(i) / double(pcount);
if (randomness_ratio > 0.0) {
uint32_t seed = cycle;
@@ -636,12 +636,12 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
seed *= uint32_t(pcount);
seed += uint32_t(i);
- float random = float(idhash(seed) % uint32_t(65536)) / 65536.0;
- restart_phase += randomness_ratio * random * 1.0 / float(pcount);
+ double random = double(idhash(seed) % uint32_t(65536)) / 65536.0;
+ restart_phase += randomness_ratio * random * 1.0 / double(pcount);
}
restart_phase *= (1.0 - explosiveness_ratio);
- float restart_time = restart_phase * lifetime;
+ double restart_time = restart_phase * lifetime;
bool restart = false;
if (time > prev_time) {
@@ -682,17 +682,17 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
p.active = true;
- /*float tex_linear_velocity = 0;
+ /*real_t tex_linear_velocity = 0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(0);
}*/
- float tex_angle = 0.0;
+ real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
- float tex_anim_offset = 0.0;
+ real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_anim_offset = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
@@ -705,26 +705,26 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.anim_offset_rand = Math::randf();
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
- float angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
+ real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0);
- p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
+ p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp((real_t)1.0, real_t(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
} else {
//initiate velocity spread in 3D
- float angle1_rad = Math::atan2(direction.x, direction.z) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
- float angle2_rad = Math::atan2(direction.y, Math::abs(direction.z)) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * spread);
+ real_t angle1_rad = Math::atan2(direction.x, direction.z) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
+ real_t angle2_rad = Math::atan2(direction.y, Math::abs(direction.z)) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * spread);
Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad));
Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad));
direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution
Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);
direction.normalize();
- p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
+ p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp((real_t)1.0, real_t(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
}
- float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
+ real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]);
p.custom[0] = Math::deg2rad(base_angle); //angle
p.custom[1] = 0.0; //phase
- p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1)
+ p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1)
p.transform = Transform3D();
p.time = 0;
p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness);
@@ -783,8 +783,8 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
} break;
case EMISSION_SHAPE_RING: {
- float ring_random_angle = Math::randf() * 2.0 * Math_PI;
- float ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
+ real_t ring_random_angle = Math::randf() * Math_TAU;
+ real_t ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
Vector3 axis = emission_ring_axis.normalized();
Vector3 ortho_axis = Vector3();
if (axis == Vector3(1.0, 0.0, 0.0)) {
@@ -824,53 +824,53 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.custom[1] = p.time / lifetime;
tv = p.time / p.lifetime;
- float tex_linear_velocity = 0.0;
+ real_t tex_linear_velocity = 0.0;
if (curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
tex_linear_velocity = curve_parameters[PARAM_INITIAL_LINEAR_VELOCITY]->interpolate(tv);
}
- float tex_orbit_velocity = 0.0;
+ real_t tex_orbit_velocity = 0.0;
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(tv);
}
}
- float tex_angular_velocity = 0.0;
+ real_t tex_angular_velocity = 0.0;
if (curve_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
tex_angular_velocity = curve_parameters[PARAM_ANGULAR_VELOCITY]->interpolate(tv);
}
- float tex_linear_accel = 0.0;
+ real_t tex_linear_accel = 0.0;
if (curve_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
tex_linear_accel = curve_parameters[PARAM_LINEAR_ACCEL]->interpolate(tv);
}
- float tex_tangential_accel = 0.0;
+ real_t tex_tangential_accel = 0.0;
if (curve_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
tex_tangential_accel = curve_parameters[PARAM_TANGENTIAL_ACCEL]->interpolate(tv);
}
- float tex_radial_accel = 0.0;
+ real_t tex_radial_accel = 0.0;
if (curve_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
tex_radial_accel = curve_parameters[PARAM_RADIAL_ACCEL]->interpolate(tv);
}
- float tex_damping = 0.0;
+ real_t tex_damping = 0.0;
if (curve_parameters[PARAM_DAMPING].is_valid()) {
tex_damping = curve_parameters[PARAM_DAMPING]->interpolate(tv);
}
- float tex_angle = 0.0;
+ real_t tex_angle = 0.0;
if (curve_parameters[PARAM_ANGLE].is_valid()) {
tex_angle = curve_parameters[PARAM_ANGLE]->interpolate(tv);
}
- float tex_anim_speed = 0.0;
+ real_t tex_anim_speed = 0.0;
if (curve_parameters[PARAM_ANIM_SPEED].is_valid()) {
tex_anim_speed = curve_parameters[PARAM_ANIM_SPEED]->interpolate(tv);
}
- float tex_anim_offset = 0.0;
+ real_t tex_anim_offset = 0.0;
if (curve_parameters[PARAM_ANIM_OFFSET].is_valid()) {
tex_anim_offset = curve_parameters[PARAM_ANIM_OFFSET]->interpolate(tv);
}
@@ -881,28 +881,28 @@ void CPUParticles3D::_particles_process(float p_delta) {
position.z = 0.0;
}
//apply linear acceleration
- force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector3();
+ force += p.velocity.length() > 0.0 ? p.velocity.normalized() * (parameters[PARAM_LINEAR_ACCEL] + tex_linear_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_LINEAR_ACCEL]) : Vector3();
//apply radial acceleration
Vector3 org = emission_xform.origin;
Vector3 diff = position - org;
- force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3();
+ force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3();
//apply tangential acceleration;
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
Vector2 yx = Vector2(diff.y, diff.x);
Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized();
- force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
+ force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
} else {
Vector3 crossDiff = diff.normalized().cross(gravity.normalized());
- force += crossDiff.length() > 0.0 ? crossDiff.normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
+ force += crossDiff.length() > 0.0 ? crossDiff.normalized() * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3();
}
//apply attractor forces
p.velocity += force * local_delta;
//orbit velocity
if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
- float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]);
+ real_t orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]);
if (orbit_amount != 0.0) {
- float ang = orbit_amount * local_delta * Math_TAU;
+ real_t ang = orbit_amount * local_delta * Math_TAU;
// Not sure why the ParticlesMaterial code uses a clockwise rotation matrix,
// but we use -ang here to reproduce its behavior.
Transform2D rot = Transform2D(-ang, Vector2());
@@ -915,8 +915,8 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.velocity = p.velocity.normalized() * tex_linear_velocity;
}
if (parameters[PARAM_DAMPING] + tex_damping > 0.0) {
- float v = p.velocity.length();
- float damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
+ real_t v = p.velocity.length();
+ real_t damp = (parameters[PARAM_DAMPING] + tex_damping) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_DAMPING]);
v -= damp * local_delta;
if (v < 0.0) {
p.velocity = Vector3();
@@ -924,27 +924,27 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.velocity = p.velocity.normalized() * v;
}
}
- float base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp(1.0f, p.angle_rand, randomness[PARAM_ANGLE]);
- base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]);
+ real_t base_angle = (parameters[PARAM_ANGLE] + tex_angle) * Math::lerp((real_t)1.0, p.angle_rand, randomness[PARAM_ANGLE]);
+ base_angle += p.custom[1] * lifetime * (parameters[PARAM_ANGULAR_VELOCITY] + tex_angular_velocity) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed) * 2.0f - 1.0f, randomness[PARAM_ANGULAR_VELOCITY]);
p.custom[0] = Math::deg2rad(base_angle); //angle
- p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); //angle
+ p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp((real_t)1.0, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]) + p.custom[1] * (parameters[PARAM_ANIM_SPEED] + tex_anim_speed) * Math::lerp((real_t)1.0, rand_from_seed(alt_seed), randomness[PARAM_ANIM_SPEED]); //angle
}
//apply color
//apply hue rotation
- float tex_scale = 1.0;
+ real_t tex_scale = 1.0;
if (curve_parameters[PARAM_SCALE].is_valid()) {
tex_scale = curve_parameters[PARAM_SCALE]->interpolate(tv);
}
- float tex_hue_variation = 0.0;
+ real_t tex_hue_variation = 0.0;
if (curve_parameters[PARAM_HUE_VARIATION].is_valid()) {
tex_hue_variation = curve_parameters[PARAM_HUE_VARIATION]->interpolate(tv);
}
- float hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1.0f, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
- float hue_rot_c = Math::cos(hue_rot_angle);
- float hue_rot_s = Math::sin(hue_rot_angle);
+ real_t hue_rot_angle = (parameters[PARAM_HUE_VARIATION] + tex_hue_variation) * Math_TAU * Math::lerp(1, p.hue_rot_rand * 2.0f - 1.0f, randomness[PARAM_HUE_VARIATION]);
+ real_t hue_rot_c = Math::cos(hue_rot_angle);
+ real_t hue_rot_s = Math::sin(hue_rot_angle);
Basis hue_rot_mat;
{
@@ -1013,9 +1013,9 @@ void CPUParticles3D::_particles_process(float p_delta) {
}
//scale by scale
- float base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], 1.0f, p.scale_rand * randomness[PARAM_SCALE]);
- if (base_scale < 0.000001) {
- base_scale = 0.000001;
+ real_t base_scale = tex_scale * Math::lerp(parameters[PARAM_SCALE], (real_t)1.0, p.scale_rand * randomness[PARAM_SCALE]);
+ if (base_scale < CMP_EPSILON) {
+ base_scale = CMP_EPSILON;
}
p.transform.basis.scale(Vector3(1, 1, 1) * base_scale);
@@ -1097,7 +1097,7 @@ void CPUParticles3D::_update_particle_data_buffer() {
ptr[10] = t.basis.elements[2][2];
ptr[11] = t.origin.z;
} else {
- memset(ptr, 0, sizeof(float) * 12);
+ memset(ptr, 0, sizeof(Transform3D));
}
Color c = r[idx].color;
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index 07d345ba2c..bb6699ddc7 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -86,23 +86,23 @@ private:
struct Particle {
Transform3D transform;
Color color;
- float custom[4] = {};
+ real_t custom[4] = {};
Vector3 velocity;
bool active = false;
- float angle_rand = 0.0;
- float scale_rand = 0.0;
- float hue_rot_rand = 0.0;
- float anim_offset_rand = 0.0;
- float time = 0.0;
- float lifetime = 0.0;
+ real_t angle_rand = 0.0;
+ real_t scale_rand = 0.0;
+ real_t hue_rot_rand = 0.0;
+ real_t anim_offset_rand = 0.0;
+ double time = 0.0;
+ double lifetime = 0.0;
Color base_color;
uint32_t seed = 0;
};
- float time = 0.0;
- float inactive_time = 0.0;
- float frame_remainder = 0.0;
+ double time = 0.0;
+ double inactive_time = 0.0;
+ double frame_remainder = 0.0;
int cycle = 0;
bool redraw = false;
@@ -132,12 +132,12 @@ private:
bool one_shot = false;
- float lifetime = 1.0;
- float pre_process_time = 0.0;
- float explosiveness_ratio = 0.0;
- float randomness_ratio = 0.0;
- float lifetime_randomness = 0.0;
- float speed_scale = 1.0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness_ratio = 0.0;
+ real_t randomness_ratio = 0.0;
+ double lifetime_randomness = 0.0;
+ double speed_scale = 1.0;
bool local_coords = true;
int fixed_fps = 0;
bool fractional_delta = true;
@@ -153,11 +153,11 @@ private:
////////
Vector3 direction = Vector3(1, 0, 0);
- float spread = 45.0;
- float flatness = 0.0;
+ real_t spread = 45.0;
+ real_t flatness = 0.0;
- float parameters[PARAM_MAX];
- float randomness[PARAM_MAX] = {};
+ real_t parameters[PARAM_MAX];
+ real_t randomness[PARAM_MAX] = {};
Ref<Curve> curve_parameters[PARAM_MAX];
Color color = Color(1, 1, 1, 1);
@@ -166,21 +166,21 @@ private:
bool particle_flags[PARTICLE_FLAG_MAX] = {};
EmissionShape emission_shape = EMISSION_SHAPE_POINT;
- float emission_sphere_radius = 1.0;
+ real_t emission_sphere_radius = 1.0;
Vector3 emission_box_extents = Vector3(1, 1, 1);
Vector<Vector3> emission_points;
Vector<Vector3> emission_normals;
Vector<Color> emission_colors;
int emission_point_count = 0;
Vector3 emission_ring_axis;
- float emission_ring_height;
- float emission_ring_radius;
- float emission_ring_inner_radius;
+ real_t emission_ring_height;
+ real_t emission_ring_radius;
+ real_t emission_ring_inner_radius;
Vector3 gravity = Vector3(0, -9.8, 0);
void _update_internal();
- void _particles_process(float p_delta);
+ void _particles_process(double p_delta);
void _update_particle_data_buffer();
Mutex update_mutex;
@@ -200,27 +200,27 @@ public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
- void set_lifetime(float p_lifetime);
+ void set_lifetime(double p_lifetime);
void set_one_shot(bool p_one_shot);
- void set_pre_process_time(float p_time);
- void set_explosiveness_ratio(float p_ratio);
- void set_randomness_ratio(float p_ratio);
- void set_lifetime_randomness(float p_random);
+ void set_pre_process_time(double p_time);
+ void set_explosiveness_ratio(real_t p_ratio);
+ void set_randomness_ratio(real_t p_ratio);
+ void set_lifetime_randomness(double p_random);
void set_visibility_aabb(const AABB &p_aabb);
void set_use_local_coordinates(bool p_enable);
- void set_speed_scale(float p_scale);
+ void set_speed_scale(double p_scale);
bool is_emitting() const;
int get_amount() const;
- float get_lifetime() const;
+ double get_lifetime() const;
bool get_one_shot() const;
- float get_pre_process_time() const;
- float get_explosiveness_ratio() const;
- float get_randomness_ratio() const;
- float get_lifetime_randomness() const;
+ double get_pre_process_time() const;
+ real_t get_explosiveness_ratio() const;
+ real_t get_randomness_ratio() const;
+ double get_lifetime_randomness() const;
AABB get_visibility_aabb() const;
bool get_use_local_coordinates() const;
- float get_speed_scale() const;
+ double get_speed_scale() const;
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
@@ -242,17 +242,17 @@ public:
void set_direction(Vector3 p_direction);
Vector3 get_direction() const;
- void set_spread(float p_spread);
- float get_spread() const;
+ void set_spread(real_t p_spread);
+ real_t get_spread() const;
- void set_flatness(float p_flatness);
- float get_flatness() const;
+ void set_flatness(real_t p_flatness);
+ real_t get_flatness() const;
- void set_param(Parameter p_param, float p_value);
- float get_param(Parameter p_param) const;
+ void set_param(Parameter p_param, real_t p_value);
+ real_t get_param(Parameter p_param) const;
- void set_param_randomness(Parameter p_param, float p_value);
- float get_param_randomness(Parameter p_param) const;
+ void set_param_randomness(Parameter p_param, real_t p_value);
+ real_t get_param_randomness(Parameter p_param) const;
void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve);
Ref<Curve> get_param_curve(Parameter p_param) const;
@@ -267,28 +267,28 @@ public:
bool get_particle_flag(ParticleFlags p_particle_flag) const;
void set_emission_shape(EmissionShape p_shape);
- void set_emission_sphere_radius(float p_radius);
+ void set_emission_sphere_radius(real_t p_radius);
void set_emission_box_extents(Vector3 p_extents);
void set_emission_points(const Vector<Vector3> &p_points);
void set_emission_normals(const Vector<Vector3> &p_normals);
void set_emission_colors(const Vector<Color> &p_colors);
void set_emission_point_count(int p_count);
void set_emission_ring_axis(Vector3 p_axis);
- void set_emission_ring_height(float p_height);
- void set_emission_ring_radius(float p_radius);
- void set_emission_ring_inner_radius(float p_radius);
+ void set_emission_ring_height(real_t p_height);
+ void set_emission_ring_radius(real_t p_radius);
+ void set_emission_ring_inner_radius(real_t p_radius);
EmissionShape get_emission_shape() const;
- float get_emission_sphere_radius() const;
+ real_t get_emission_sphere_radius() const;
Vector3 get_emission_box_extents() const;
Vector<Vector3> get_emission_points() const;
Vector<Vector3> get_emission_normals() const;
Vector<Color> get_emission_colors() const;
int get_emission_point_count() const;
Vector3 get_emission_ring_axis() const;
- float get_emission_ring_height() const;
- float get_emission_ring_radius() const;
- float get_emission_ring_inner_radius() const;
+ real_t get_emission_ring_height() const;
+ real_t get_emission_ring_radius() const;
+ real_t get_emission_ring_inner_radius() const;
void set_gravity(const Vector3 &p_gravity);
Vector3 get_gravity() const;
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 05f023721b..c94a99a203 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -53,48 +53,48 @@ Ref<Texture2D> Decal::get_texture(DecalTexture p_type) const {
return textures[p_type];
}
-void Decal::set_emission_energy(float p_energy) {
+void Decal::set_emission_energy(real_t p_energy) {
emission_energy = p_energy;
RS::get_singleton()->decal_set_emission_energy(decal, emission_energy);
}
-float Decal::get_emission_energy() const {
+real_t Decal::get_emission_energy() const {
return emission_energy;
}
-void Decal::set_albedo_mix(float p_mix) {
+void Decal::set_albedo_mix(real_t p_mix) {
albedo_mix = p_mix;
RS::get_singleton()->decal_set_albedo_mix(decal, albedo_mix);
}
-float Decal::get_albedo_mix() const {
+real_t Decal::get_albedo_mix() const {
return albedo_mix;
}
-void Decal::set_upper_fade(float p_fade) {
+void Decal::set_upper_fade(real_t p_fade) {
upper_fade = p_fade;
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
-float Decal::get_upper_fade() const {
+real_t Decal::get_upper_fade() const {
return upper_fade;
}
-void Decal::set_lower_fade(float p_fade) {
+void Decal::set_lower_fade(real_t p_fade) {
lower_fade = p_fade;
RS::get_singleton()->decal_set_fade(decal, upper_fade, lower_fade);
}
-float Decal::get_lower_fade() const {
+real_t Decal::get_lower_fade() const {
return lower_fade;
}
-void Decal::set_normal_fade(float p_fade) {
+void Decal::set_normal_fade(real_t p_fade) {
normal_fade = p_fade;
RS::get_singleton()->decal_set_normal_fade(decal, normal_fade);
}
-float Decal::get_normal_fade() const {
+real_t Decal::get_normal_fade() const {
return normal_fade;
}
@@ -117,21 +117,21 @@ bool Decal::is_distance_fade_enabled() const {
return distance_fade_enabled;
}
-void Decal::set_distance_fade_begin(float p_distance) {
+void Decal::set_distance_fade_begin(real_t p_distance) {
distance_fade_begin = p_distance;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
}
-float Decal::get_distance_fade_begin() const {
+real_t Decal::get_distance_fade_begin() const {
return distance_fade_begin;
}
-void Decal::set_distance_fade_length(float p_length) {
+void Decal::set_distance_fade_length(real_t p_length) {
distance_fade_length = p_length;
RS::get_singleton()->decal_set_distance_fade(decal, distance_fade_enabled, distance_fade_begin, distance_fade_length);
}
-float Decal::get_distance_fade_length() const {
+real_t Decal::get_distance_fade_length() const {
return distance_fade_length;
}
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index 31a6315213..041c8f97b2 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -51,16 +51,16 @@ private:
RID decal;
Vector3 extents = Vector3(1, 1, 1);
Ref<Texture2D> textures[TEXTURE_MAX];
- float emission_energy = 1.0;
- float albedo_mix = 1.0;
+ real_t emission_energy = 1.0;
+ real_t albedo_mix = 1.0;
Color modulate = Color(1, 1, 1, 1);
uint32_t cull_mask = (1 << 20) - 1;
- float normal_fade = 0.0;
- float upper_fade = 0.3;
- float lower_fade = 0.3;
+ real_t normal_fade = 0.0;
+ real_t upper_fade = 0.3;
+ real_t lower_fade = 0.3;
bool distance_fade_enabled = false;
- float distance_fade_begin = 10.0;
- float distance_fade_length = 1.0;
+ real_t distance_fade_begin = 10.0;
+ real_t distance_fade_length = 1.0;
protected:
static void _bind_methods();
@@ -75,32 +75,32 @@ public:
void set_texture(DecalTexture p_type, const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture(DecalTexture p_type) const;
- void set_emission_energy(float p_energy);
- float get_emission_energy() const;
+ void set_emission_energy(real_t p_energy);
+ real_t get_emission_energy() const;
- void set_albedo_mix(float p_mix);
- float get_albedo_mix() const;
+ void set_albedo_mix(real_t p_mix);
+ real_t get_albedo_mix() const;
void set_modulate(Color p_modulate);
Color get_modulate() const;
- void set_upper_fade(float p_energy);
- float get_upper_fade() const;
+ void set_upper_fade(real_t p_energy);
+ real_t get_upper_fade() const;
- void set_lower_fade(float p_fade);
- float get_lower_fade() const;
+ void set_lower_fade(real_t p_fade);
+ real_t get_lower_fade() const;
- void set_normal_fade(float p_fade);
- float get_normal_fade() const;
+ void set_normal_fade(real_t p_fade);
+ real_t get_normal_fade() const;
void set_enable_distance_fade(bool p_enable);
bool is_distance_fade_enabled() const;
- void set_distance_fade_begin(float p_distance);
- float get_distance_fade_begin() const;
+ void set_distance_fade_begin(real_t p_distance);
+ real_t get_distance_fade_begin() const;
- void set_distance_fade_length(float p_length);
- float get_distance_fade_length() const;
+ void set_distance_fade_length(real_t p_length);
+ real_t get_distance_fade_length() const;
void set_cull_mask(uint32_t p_layers);
uint32_t get_cull_mask() const;
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 44cd7c10d8..8b8b53c3bf 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -59,7 +59,7 @@ void GPUParticles3D::set_amount(int p_amount) {
RS::get_singleton()->particles_set_amount(particles, amount);
}
-void GPUParticles3D::set_lifetime(float p_lifetime) {
+void GPUParticles3D::set_lifetime(double p_lifetime) {
ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0.");
lifetime = p_lifetime;
RS::get_singleton()->particles_set_lifetime(particles, lifetime);
@@ -81,7 +81,7 @@ void GPUParticles3D::set_one_shot(bool p_one_shot) {
}
}
-void GPUParticles3D::set_pre_process_time(float p_time) {
+void GPUParticles3D::set_pre_process_time(double p_time) {
pre_process_time = p_time;
RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time);
}
@@ -118,7 +118,7 @@ void GPUParticles3D::set_process_material(const Ref<Material> &p_material) {
update_configuration_warnings();
}
-void GPUParticles3D::set_speed_scale(float p_scale) {
+void GPUParticles3D::set_speed_scale(double p_scale) {
speed_scale = p_scale;
RS::get_singleton()->particles_set_speed_scale(particles, p_scale);
}
@@ -136,7 +136,7 @@ int GPUParticles3D::get_amount() const {
return amount;
}
-float GPUParticles3D::get_lifetime() const {
+double GPUParticles3D::get_lifetime() const {
return lifetime;
}
@@ -144,7 +144,7 @@ bool GPUParticles3D::get_one_shot() const {
return one_shot;
}
-float GPUParticles3D::get_pre_process_time() const {
+double GPUParticles3D::get_pre_process_time() const {
return pre_process_time;
}
@@ -168,7 +168,7 @@ Ref<Material> GPUParticles3D::get_process_material() const {
return process_material;
}
-float GPUParticles3D::get_speed_scale() const {
+double GPUParticles3D::get_speed_scale() const {
return speed_scale;
}
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 7b21cf03f1..31e0e2abf5 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -64,11 +64,11 @@ private:
bool one_shot;
int amount;
- float lifetime;
- float pre_process_time;
+ double lifetime;
+ double pre_process_time;
float explosiveness_ratio;
float randomness_ratio;
- float speed_scale;
+ double speed_scale;
AABB visibility_aabb;
bool local_coords;
int fixed_fps;
@@ -104,30 +104,30 @@ public:
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
- void set_lifetime(float p_lifetime);
+ void set_lifetime(double p_lifetime);
void set_one_shot(bool p_one_shot);
- void set_pre_process_time(float p_time);
+ void set_pre_process_time(double p_time);
void set_explosiveness_ratio(float p_ratio);
void set_randomness_ratio(float p_ratio);
void set_visibility_aabb(const AABB &p_aabb);
void set_use_local_coordinates(bool p_enable);
void set_process_material(const Ref<Material> &p_material);
- void set_speed_scale(float p_scale);
+ void set_speed_scale(double p_scale);
void set_collision_base_size(float p_ratio);
void set_trail_enabled(bool p_enabled);
void set_trail_length(float p_seconds);
bool is_emitting() const;
int get_amount() const;
- float get_lifetime() const;
+ double get_lifetime() const;
bool get_one_shot() const;
- float get_pre_process_time() const;
+ double get_pre_process_time() const;
float get_explosiveness_ratio() const;
float get_randomness_ratio() const;
AABB get_visibility_aabb() const;
bool get_use_local_coordinates() const;
Ref<Material> get_process_material() const;
- float get_speed_scale() const;
+ double get_speed_scale() const;
float get_collision_base_size() const;
bool is_trail_enabled() const;
float get_trail_length() const;
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index c2943a9606..40f33dfa72 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -38,7 +38,7 @@ bool Light3D::_can_gizmo_scale() const {
return false;
}
-void Light3D::set_param(Param p_param, float p_value) {
+void Light3D::set_param(Param p_param, real_t p_value) {
ERR_FAIL_INDEX(p_param, PARAM_MAX);
param[p_param] = p_value;
@@ -53,7 +53,7 @@ void Light3D::set_param(Param p_param, float p_value) {
}
}
-float Light3D::get_param(Param p_param) const {
+real_t Light3D::get_param(Param p_param) const {
ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0);
return param[p_param];
}
@@ -128,8 +128,8 @@ AABB Light3D::get_aabb() const {
return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
} else if (type == RenderingServer::LIGHT_SPOT) {
- float len = param[PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len;
+ real_t len = param[PARAM_RANGE];
+ real_t size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
}
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index d0308a3025..51ed2fcf50 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -71,7 +71,7 @@ public:
private:
Color color;
- float param[PARAM_MAX] = {};
+ real_t param[PARAM_MAX] = {};
Color shadow_color;
bool shadow = false;
bool negative = false;
@@ -102,8 +102,8 @@ public:
void set_editor_only(bool p_editor_only);
bool is_editor_only() const;
- void set_param(Param p_param, float p_value);
- float get_param(Param p_param) const;
+ void set_param(Param p_param, real_t p_value);
+ real_t get_param(Param p_param) const;
void set_shadow(bool p_enable);
bool has_shadow() const;
diff --git a/scene/3d/listener_3d.cpp b/scene/3d/listener_3d.cpp
index 636be083ab..43d6f262d8 100644
--- a/scene/3d/listener_3d.cpp
+++ b/scene/3d/listener_3d.cpp
@@ -73,14 +73,14 @@ void Listener3D::_get_property_list(List<PropertyInfo> *p_list) const {
void Listener3D::_update_listener() {
if (is_inside_tree() && is_current()) {
- get_viewport()->_listener_transform_changed_notify();
+ get_viewport()->_listener_transform_3d_changed_notify();
}
}
void Listener3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
- bool first_listener = get_viewport()->_listener_add(this);
+ bool first_listener = get_viewport()->_listener_3d_add(this);
if (!get_tree()->is_node_being_edited(this) && (current || first_listener)) {
make_current();
}
@@ -99,7 +99,7 @@ void Listener3D::_notification(int p_what) {
}
}
- get_viewport()->_listener_remove(this);
+ get_viewport()->_listener_3d_remove(this);
} break;
}
@@ -116,7 +116,7 @@ void Listener3D::make_current() {
return;
}
- get_viewport()->_listener_set(this);
+ get_viewport()->_listener_3d_set(this);
}
void Listener3D::clear_current() {
@@ -125,15 +125,15 @@ void Listener3D::clear_current() {
return;
}
- if (get_viewport()->get_listener() == this) {
- get_viewport()->_listener_set(nullptr);
- get_viewport()->_listener_make_next_current(this);
+ if (get_viewport()->get_listener_3d() == this) {
+ get_viewport()->_listener_3d_set(nullptr);
+ get_viewport()->_listener_3d_make_next_current(this);
}
}
bool Listener3D::is_current() const {
if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) {
- return get_viewport()->get_listener() == this;
+ return get_viewport()->get_listener_3d() == this;
} else {
return current;
}
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 0daee69ee5..8f186199db 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -588,31 +588,31 @@ bool Node3D::is_visible() const {
return data.visible;
}
-void Node3D::rotate_object_local(const Vector3 &p_axis, float p_angle) {
+void Node3D::rotate_object_local(const Vector3 &p_axis, real_t p_angle) {
Transform3D t = get_transform();
t.basis.rotate_local(p_axis, p_angle);
set_transform(t);
}
-void Node3D::rotate(const Vector3 &p_axis, float p_angle) {
+void Node3D::rotate(const Vector3 &p_axis, real_t p_angle) {
Transform3D t = get_transform();
t.basis.rotate(p_axis, p_angle);
set_transform(t);
}
-void Node3D::rotate_x(float p_angle) {
+void Node3D::rotate_x(real_t p_angle) {
Transform3D t = get_transform();
t.basis.rotate(Vector3(1, 0, 0), p_angle);
set_transform(t);
}
-void Node3D::rotate_y(float p_angle) {
+void Node3D::rotate_y(real_t p_angle) {
Transform3D t = get_transform();
t.basis.rotate(Vector3(0, 1, 0), p_angle);
set_transform(t);
}
-void Node3D::rotate_z(float p_angle) {
+void Node3D::rotate_z(real_t p_angle) {
Transform3D t = get_transform();
t.basis.rotate(Vector3(0, 0, 1), p_angle);
set_transform(t);
@@ -644,7 +644,7 @@ void Node3D::scale_object_local(const Vector3 &p_scale) {
set_transform(t);
}
-void Node3D::global_rotate(const Vector3 &p_axis, float p_angle) {
+void Node3D::global_rotate(const Vector3 &p_axis, real_t p_angle) {
Transform3D t = get_global_transform();
t.basis.rotate(p_axis, p_angle);
set_global_transform(t);
@@ -673,19 +673,17 @@ void Node3D::set_identity() {
}
void Node3D::look_at(const Vector3 &p_target, const Vector3 &p_up) {
- Vector3 origin(get_global_transform().origin);
+ Vector3 origin = get_global_transform().origin;
look_at_from_position(origin, p_target, p_up);
}
void Node3D::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up) {
- ERR_FAIL_COND_MSG(p_pos == p_target, "Node origin and target are in the same position, look_at() failed.");
- ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos) == Vector3(), "Up vector and direction between node origin and target are aligned, look_at() failed.");
+ ERR_FAIL_COND_MSG(p_pos.is_equal_approx(p_target), "Node origin and target are in the same position, look_at() failed.");
+ ERR_FAIL_COND_MSG(p_up.is_equal_approx(Vector3()), "The up vector can't be zero, look_at() failed.");
+ ERR_FAIL_COND_MSG(p_up.cross(p_target - p_pos).is_equal_approx(Vector3()), "Up vector and direction between node origin and target are aligned, look_at() failed.");
- Transform3D lookat;
- lookat.origin = p_pos;
-
- Vector3 original_scale(get_scale());
- lookat = lookat.looking_at(p_target, p_up);
+ Transform3D lookat = Transform3D(Basis::looking_at(p_target - p_pos, p_up), p_pos);
+ Vector3 original_scale = get_scale();
set_global_transform(lookat);
set_scale(original_scale);
}
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index 282f4805cc..da54452abb 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -167,18 +167,18 @@ public:
Transform3D get_relative_transform(const Node *p_parent) const;
- void rotate(const Vector3 &p_axis, float p_angle);
- void rotate_x(float p_angle);
- void rotate_y(float p_angle);
- void rotate_z(float p_angle);
+ void rotate(const Vector3 &p_axis, real_t p_angle);
+ void rotate_x(real_t p_angle);
+ void rotate_y(real_t p_angle);
+ void rotate_z(real_t p_angle);
void translate(const Vector3 &p_offset);
void scale(const Vector3 &p_ratio);
- void rotate_object_local(const Vector3 &p_axis, float p_angle);
+ void rotate_object_local(const Vector3 &p_axis, real_t p_angle);
void scale_object_local(const Vector3 &p_scale);
void translate_object_local(const Vector3 &p_offset);
- void global_rotate(const Vector3 &p_axis, float p_angle);
+ void global_rotate(const Vector3 &p_axis, real_t p_angle);
void global_scale(const Vector3 &p_scale);
void global_translate(const Vector3 &p_offset);
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 589135710f..6818acf69d 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -94,13 +94,13 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
return;
}
- float bl = c->get_baked_length();
+ real_t bl = c->get_baked_length();
if (bl == 0.0) {
return;
}
- float bi = c->get_bake_interval();
- float o_next = offset + bi;
- float o_prev = offset - bi;
+ real_t bi = c->get_bake_interval();
+ real_t o_next = offset + bi;
+ real_t o_prev = offset - bi;
if (loop) {
o_next = Math::fposmod(o_next, bl);
@@ -169,8 +169,8 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
Vector3 t_cur = (c->interpolate_baked(offset + delta_offset, cubic) - pos).normalized();
Vector3 axis = t_prev.cross(t_cur);
- float dot = t_prev.dot(t_cur);
- float angle = Math::acos(CLAMP(dot, -1, 1));
+ real_t dot = t_prev.dot(t_cur);
+ real_t angle = Math::acos(CLAMP(dot, -1, 1));
if (likely(!Math::is_zero_approx(angle))) {
if (rotation_mode == ROTATION_Y) {
@@ -189,7 +189,7 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
}
// do the additional tilting
- float tilt_angle = c->interpolate_baked_tilt(offset);
+ real_t tilt_angle = c->interpolate_baked_tilt(offset);
Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
@@ -244,7 +244,7 @@ bool PathFollow3D::get_cubic_interpolation() const {
void PathFollow3D::_validate_property(PropertyInfo &property) const {
if (property.name == "offset") {
- float max = 10000;
+ real_t max = 10000;
if (path && path->get_curve().is_valid()) {
max = path->get_curve()->get_baked_length();
}
@@ -307,13 +307,13 @@ void PathFollow3D::_bind_methods() {
BIND_ENUM_CONSTANT(ROTATION_ORIENTED);
}
-void PathFollow3D::set_offset(float p_offset) {
+void PathFollow3D::set_offset(real_t p_offset) {
delta_offset = p_offset - offset;
offset = p_offset;
if (path) {
if (path->get_curve().is_valid()) {
- float path_length = path->get_curve()->get_baked_length();
+ real_t path_length = path->get_curve()->get_baked_length();
if (loop) {
offset = Math::fposmod(offset, path_length);
@@ -329,39 +329,39 @@ void PathFollow3D::set_offset(float p_offset) {
}
}
-void PathFollow3D::set_h_offset(float p_h_offset) {
+void PathFollow3D::set_h_offset(real_t p_h_offset) {
h_offset = p_h_offset;
if (path) {
_update_transform();
}
}
-float PathFollow3D::get_h_offset() const {
+real_t PathFollow3D::get_h_offset() const {
return h_offset;
}
-void PathFollow3D::set_v_offset(float p_v_offset) {
+void PathFollow3D::set_v_offset(real_t p_v_offset) {
v_offset = p_v_offset;
if (path) {
_update_transform();
}
}
-float PathFollow3D::get_v_offset() const {
+real_t PathFollow3D::get_v_offset() const {
return v_offset;
}
-float PathFollow3D::get_offset() const {
+real_t PathFollow3D::get_offset() const {
return offset;
}
-void PathFollow3D::set_unit_offset(float p_unit_offset) {
+void PathFollow3D::set_unit_offset(real_t p_unit_offset) {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
set_offset(p_unit_offset * path->get_curve()->get_baked_length());
}
}
-float PathFollow3D::get_unit_offset() const {
+real_t PathFollow3D::get_unit_offset() const {
if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) {
return get_offset() / path->get_curve()->get_baked_length();
} else {
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index 8545370a4a..1ffe291100 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -83,17 +83,17 @@ protected:
static void _bind_methods();
public:
- void set_offset(float p_offset);
- float get_offset() const;
+ void set_offset(real_t p_offset);
+ real_t get_offset() const;
- void set_h_offset(float p_h_offset);
- float get_h_offset() const;
+ void set_h_offset(real_t p_h_offset);
+ real_t get_h_offset() const;
- void set_v_offset(float p_v_offset);
- float get_v_offset() const;
+ void set_v_offset(real_t p_v_offset);
+ real_t get_v_offset() const;
- void set_unit_offset(float p_unit_offset);
- float get_unit_offset() const;
+ void set_unit_offset(real_t p_unit_offset);
+ real_t get_unit_offset() const;
void set_loop(bool p_loop);
bool has_loop() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 100e3563a3..53ec07f1ce 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -117,9 +117,9 @@ Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_i
return Ref<KinematicCollision3D>();
}
-bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding) {
+bool PhysicsBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding, const Set<RID> &p_exclude) {
Transform3D gt = get_global_transform();
- bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes);
+ bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes, p_exclude);
// Restore direction of motion to be along original motion,
// in order to avoid sliding due to recovery,
@@ -1090,6 +1090,9 @@ void CharacterBody3D::move_and_slide() {
bool was_on_floor = on_floor;
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
+ float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time();
+
for (int i = 0; i < 3; i++) {
if (locked_axis & (1 << i)) {
linear_velocity[i] = 0.0;
@@ -1097,28 +1100,40 @@ void CharacterBody3D::move_and_slide() {
}
Vector3 current_floor_velocity = floor_velocity;
- if (on_floor && on_floor_body.is_valid()) {
+ if ((on_floor || on_wall) && on_floor_body.is_valid()) {
//this approach makes sure there is less delay between the actual body velocity and the one we saved
PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(on_floor_body);
if (bs) {
- current_floor_velocity = bs->get_linear_velocity();
+ Transform3D gt = get_global_transform();
+ Vector3 local_position = gt.origin - bs->get_transform().origin;
+ current_floor_velocity = bs->get_velocity_at_local_position(local_position);
}
}
- // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
- Vector3 motion = (floor_velocity + linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
-
+ motion_results.clear();
on_floor = false;
- on_floor_body = RID();
on_ceiling = false;
on_wall = false;
- motion_results.clear();
floor_normal = Vector3();
floor_velocity = Vector3();
+ if (current_floor_velocity != Vector3() && on_floor_body.is_valid()) {
+ PhysicsServer3D::MotionResult floor_result;
+ Set<RID> exclude;
+ exclude.insert(on_floor_body);
+ if (move_and_collide(current_floor_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) {
+ motion_results.push_back(floor_result);
+ _set_collision_direction(floor_result);
+ }
+ }
+
+ on_floor_body = RID();
+ Vector3 motion = linear_velocity * delta;
+
// No sliding on first attempt to keep floor motion stable when possible,
// when stop on slope is enabled.
bool sliding_enabled = !stop_on_slope;
+
for (int iteration = 0; iteration < max_slides; ++iteration) {
PhysicsServer3D::MotionResult result;
bool found_collision = false;
@@ -1142,35 +1157,19 @@ void CharacterBody3D::move_and_slide() {
found_collision = true;
motion_results.push_back(result);
-
- if (up_direction == Vector3()) {
- //all is a wall
- on_wall = true;
- } else {
- if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
-
- on_floor = true;
- floor_normal = result.collision_normal;
- on_floor_body = result.collider;
- floor_velocity = result.collider_velocity;
-
- if (stop_on_slope) {
- if ((body_velocity_normal + up_direction).length() < 0.01) {
- Transform3D gt = get_global_transform();
- if (result.motion.length() > margin) {
- gt.origin -= result.motion.slide(up_direction);
- } else {
- gt.origin -= result.motion;
- }
- set_global_transform(gt);
- linear_velocity = Vector3();
- return;
- }
+ _set_collision_direction(result);
+
+ if (on_floor && stop_on_slope) {
+ if ((body_velocity_normal + up_direction).length() < 0.01) {
+ Transform3D gt = get_global_transform();
+ if (result.motion.length() > margin) {
+ gt.origin -= result.motion.slide(up_direction);
+ } else {
+ gt.origin -= result.motion;
}
- } else if (Math::acos(result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
- on_ceiling = true;
- } else {
- on_wall = true;
+ set_global_transform(gt);
+ linear_velocity = Vector3();
+ return;
}
}
@@ -1196,6 +1195,11 @@ void CharacterBody3D::move_and_slide() {
}
}
+ if (!on_floor && !on_wall) {
+ // Add last platform velocity when just left a moving platform.
+ linear_velocity += current_floor_velocity;
+ }
+
if (!was_on_floor || snap == Vector3()) {
return;
}
@@ -1231,6 +1235,29 @@ void CharacterBody3D::move_and_slide() {
}
}
+void CharacterBody3D::_set_collision_direction(const PhysicsServer3D::MotionResult &p_result) {
+ on_floor = false;
+ on_ceiling = false;
+ on_wall = false;
+ if (up_direction == Vector3()) {
+ //all is a wall
+ on_wall = true;
+ } else {
+ if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+ on_floor = true;
+ floor_normal = p_result.collision_normal;
+ on_floor_body = p_result.collider;
+ floor_velocity = p_result.collider_velocity;
+ } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+ on_ceiling = true;
+ } else {
+ on_wall = true;
+ on_floor_body = p_result.collider;
+ floor_velocity = p_result.collider_velocity;
+ }
+ }
+}
+
bool CharacterBody3D::separate_raycast_shapes(PhysicsServer3D::MotionResult &r_result) {
PhysicsServer3D::SeparationResult sep_res[8]; //max 8 rays
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 0ef9c78f3b..227e6d43b6 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -53,7 +53,7 @@ protected:
Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false, real_t p_margin = 0.001);
public:
- bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true);
+ bool move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes = true, bool p_test_only = false, bool p_cancel_sliding = true, const Set<RID> &p_exclude = Set<RID>());
bool test_move(const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
@@ -298,6 +298,8 @@ private:
Ref<KinematicCollision3D> _get_slide_collision(int p_bounce);
+ void _set_collision_direction(const PhysicsServer3D::MotionResult &p_result);
+
bool separate_raycast_shapes(PhysicsServer3D::MotionResult &r_result);
void set_safe_margin(real_t p_margin);
diff --git a/scene/3d/proximity_group_3d.h b/scene/3d/proximity_group_3d.h
index 05aa00b228..e45adc3040 100644
--- a/scene/3d/proximity_group_3d.h
+++ b/scene/3d/proximity_group_3d.h
@@ -49,7 +49,7 @@ private:
DispatchMode dispatch_mode = MODE_PROXY;
Vector3 grid_radius = Vector3(1, 1, 1);
- float cell_size = 1.0;
+ real_t cell_size = 1.0;
uint32_t group_version = 0;
void _clear_groups();
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 9ce4c37457..86e2af7df5 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -366,7 +366,7 @@ void Skeleton3D::clear_bones_global_pose_override() {
_make_dirty();
}
-void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount, bool p_persistent) {
+void Skeleton3D::set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent) {
ERR_FAIL_INDEX(p_bone, bones.size());
bones.write[p_bone].global_pose_override_amount = p_amount;
bones.write[p_bone].global_pose_override = p_pose;
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 2f6e416c8c..3fdf5321a5 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -85,7 +85,7 @@ private:
bool custom_pose_enable = false;
Transform3D custom_pose;
- float global_pose_override_amount = 0.0;
+ real_t global_pose_override_amount = 0.0;
bool global_pose_override_reset = false;
Transform3D global_pose_override;
@@ -147,7 +147,7 @@ public:
Transform3D get_bone_global_pose_no_override(int p_bone) const;
void clear_bones_global_pose_override();
- void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, float p_amount, bool p_persistent = false);
+ void set_bone_global_pose_override(int p_bone, const Transform3D &p_pose, real_t p_amount, bool p_persistent = false);
void set_bone_enabled(int p_bone, bool p_enabled);
bool is_bone_enabled(int p_bone) const;
diff --git a/scene/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 1005d51e63..a891566633 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -85,7 +85,7 @@ bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
chain_sub_tip = p_task->skeleton->get_bone_parent(chain_sub_tip);
}
- BoneId middle_chain_item_id = (((float)sub_chain_size) * 0.5);
+ BoneId middle_chain_item_id = (BoneId)(sub_chain_size * 0.5);
// Build chain by reading chain ids in reverse order
// For each chain item id will be created a ChainItem if doesn't exists
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index a901920dbe..a28382f4cb 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -132,12 +132,12 @@ Color SpriteBase3D::get_modulate() const {
return modulate;
}
-void SpriteBase3D::set_pixel_size(float p_amount) {
+void SpriteBase3D::set_pixel_size(real_t p_amount) {
pixel_size = p_amount;
_queue_update();
}
-float SpriteBase3D::get_pixel_size() const {
+real_t SpriteBase3D::get_pixel_size() const {
return pixel_size;
}
@@ -203,7 +203,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
return Ref<TriangleMesh>();
}
- float pixel_size = get_pixel_size();
+ real_t pixel_size = get_pixel_size();
Vector2 vertices[4] = {
@@ -470,7 +470,7 @@ void Sprite3D::_draw() {
Color color = _get_color_accum();
color.a *= get_opacity();
- float pixel_size = get_pixel_size();
+ real_t pixel_size = get_pixel_size();
Vector2 vertices[4] = {
@@ -837,7 +837,7 @@ void AnimatedSprite3D::_draw() {
Color color = _get_color_accum();
color.a *= get_opacity();
- float pixel_size = get_pixel_size();
+ real_t pixel_size = get_pixel_size();
Vector2 vertices[4] = {
@@ -1037,7 +1037,7 @@ void AnimatedSprite3D::_notification(int p_what) {
return; //do nothing
}
- float remaining = get_process_delta_time();
+ double remaining = get_process_delta_time();
while (remaining) {
if (timeout <= 0) {
@@ -1059,7 +1059,7 @@ void AnimatedSprite3D::_notification(int p_what) {
emit_signal(SceneStringNames::get_singleton()->frame_changed);
}
- float to_process = MIN(timeout, remaining);
+ double to_process = MIN(timeout, remaining);
remaining -= to_process;
timeout -= to_process;
}
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 404ef57e6a..d35b9ffe1b 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -72,7 +72,7 @@ private:
float opacity = 1.0;
Vector3::Axis axis = Vector3::AXIS_Z;
- float pixel_size = 0.01;
+ real_t pixel_size = 0.01;
AABB aabb;
RID mesh;
@@ -130,8 +130,8 @@ public:
void set_opacity(float p_amount);
float get_opacity() const;
- void set_pixel_size(float p_amount);
- float get_pixel_size() const;
+ void set_pixel_size(real_t p_amount);
+ real_t get_pixel_size() const;
void set_axis(Vector3::Axis p_axis);
Vector3::Axis get_axis() const;
@@ -213,7 +213,7 @@ class AnimatedSprite3D : public SpriteBase3D {
bool centered = false;
- float timeout = 0;
+ double timeout = 0.0;
void _res_changed();
diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp
index 5b5cc06456..a027749eaa 100644
--- a/scene/3d/velocity_tracker_3d.cpp
+++ b/scene/3d/velocity_tracker_3d.cpp
@@ -61,16 +61,16 @@ void VelocityTracker3D::update_position(const Vector3 &p_position) {
Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
Vector3 linear_velocity;
- float max_time = 1 / 5.0; //maximum time to interpolate a velocity
+ double max_time = 1 / 5.0; //maximum time to interpolate a velocity
Vector3 distance_accum;
- float time_accum = 0.0;
- float base_time = 0.0;
+ double time_accum = 0.0;
+ double base_time = 0.0;
if (position_history_len) {
if (physics_step) {
uint64_t base = Engine::get_singleton()->get_physics_frames();
- base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second();
+ base_time = double(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second();
} else {
uint64_t base = Engine::get_singleton()->get_frame_ticks();
base_time = double(base - position_history[0].frame) / 1000000.0;
@@ -78,12 +78,12 @@ Vector3 VelocityTracker3D::get_tracked_linear_velocity() const {
}
for (int i = 0; i < position_history_len - 1; i++) {
- float delta = 0.0;
+ double delta = 0.0;
uint64_t diff = position_history[i].frame - position_history[i + 1].frame;
Vector3 distance = position_history[i].position - position_history[i + 1].position;
if (physics_step) {
- delta = float(diff) / Engine::get_singleton()->get_iterations_per_second();
+ delta = double(diff) / Engine::get_singleton()->get_iterations_per_second();
} else {
delta = double(diff) / 1000000.0;
}
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index f1b9708f91..6124326d2d 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -56,20 +56,20 @@ static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3
Vector3 v1 = p_vtx[2] - p_vtx[0];
Vector3 v2 = p_pos - p_vtx[0];
- float d00 = v0.dot(v0);
- float d01 = v0.dot(v1);
- float d11 = v1.dot(v1);
- float d20 = v2.dot(v0);
- float d21 = v2.dot(v1);
- float denom = (d00 * d11 - d01 * d01);
+ real_t d00 = v0.dot(v0);
+ real_t d01 = v0.dot(v1);
+ real_t d11 = v1.dot(v1);
+ real_t d20 = v2.dot(v0);
+ real_t d21 = v2.dot(v1);
+ real_t denom = (d00 * d11 - d01 * d01);
if (denom == 0) {
r_uv = p_uv[0];
r_normal = p_normal[0];
return;
}
- float v = (d11 * d20 - d01 * d21) / denom;
- float w = (d00 * d21 - d01 * d20) / denom;
- float u = 1.0f - v - w;
+ real_t v = (d11 * d20 - d01 * d21) / denom;
+ real_t w = (d00 * d21 - d01 * d20) / denom;
+ real_t u = 1.0f - v - w;
r_uv = p_uv[0] * u + p_uv[1] * v + p_uv[2] * w;
r_normal = (p_normal[0] * u + p_normal[1] * v + p_normal[2] * w).normalized();
@@ -81,7 +81,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
//find best axis to map to, for scanning values
int closest_axis = 0;
- float closest_dot = 0;
+ real_t closest_dot = 0;
Plane plane = Plane(p_vtx[0], p_vtx[1], p_vtx[2]);
Vector3 normal = plane.normal;
@@ -89,7 +89,7 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
for (int i = 0; i < 3; i++) {
Vector3 axis;
axis[i] = 1.0;
- float dot = ABS(normal.dot(axis));
+ real_t dot = ABS(normal.dot(axis));
if (i == 0 || dot > closest_dot) {
closest_axis = i;
closest_dot = dot;
@@ -103,8 +103,8 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
Vector3 t2;
t2[(closest_axis + 2) % 3] = 1.0;
- t1 *= p_aabb.size[(closest_axis + 1) % 3] / float(color_scan_cell_width);
- t2 *= p_aabb.size[(closest_axis + 2) % 3] / float(color_scan_cell_width);
+ t1 *= p_aabb.size[(closest_axis + 1) % 3] / real_t(color_scan_cell_width);
+ t2 *= p_aabb.size[(closest_axis + 2) % 3] / real_t(color_scan_cell_width);
Color albedo_accum;
Color emission_accum;
@@ -114,10 +114,10 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
//map to a grid average in the best axis for this face
for (int i = 0; i < color_scan_cell_width; i++) {
- Vector3 ofs_i = float(i) * t1;
+ Vector3 ofs_i = real_t(i) * t1;
for (int j = 0; j < color_scan_cell_width; j++) {
- Vector3 ofs_j = float(j) * t2;
+ Vector3 ofs_j = real_t(j) * t2;
Vector3 from = p_aabb.position + ofs_i + ofs_j;
Vector3 to = from + t1 + t2 + axis * p_aabb.size[closest_axis];
@@ -155,8 +155,8 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
lnormal = normal;
}
- int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
- int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
+ int uv_x = CLAMP(int(Math::fposmod(uv.x, (real_t)1.0) * bake_texture_size), 0, bake_texture_size - 1);
+ int uv_y = CLAMP(int(Math::fposmod(uv.y, (real_t)1.0) * bake_texture_size), 0, bake_texture_size - 1);
int ofs = uv_y * bake_texture_size + uv_x;
albedo_accum.r += p_material.albedo[ofs].r;
@@ -187,8 +187,8 @@ void Voxelizer::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p_z, co
lnormal = normal;
}
- int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
- int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
+ int uv_x = CLAMP(Math::fposmod(uv.x, (real_t)1.0) * bake_texture_size, 0, bake_texture_size - 1);
+ int uv_y = CLAMP(Math::fposmod(uv.y, (real_t)1.0) * bake_texture_size, 0, bake_texture_size - 1);
int ofs = uv_y * bake_texture_size + uv_x;
@@ -636,7 +636,7 @@ void Voxelizer::begin_bake(int p_subdiv, const AABB &p_bounds) {
}
axis_cell_size[i] = axis_cell_size[longest_axis];
- float axis_size = po2_bounds.size[longest_axis];
+ real_t axis_size = po2_bounds.size[longest_axis];
//shrink until fit subdiv
while (axis_size / 2.0 >= po2_bounds.size[i]) {
@@ -954,7 +954,7 @@ Ref<MultiMesh> Voxelizer::create_debug_multimesh() {
Vector3 face_points[4];
for (int j = 0; j < 4; j++) {
- float v[3];
+ real_t v[3];
v[0] = 1.0;
v[1] = 1 - 2 * ((j >> 1) & 1);
v[2] = v[1] * (1 - 2 * (j & 1));
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index b04c7e2858..e620f33478 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -124,7 +124,7 @@ Point2 XRCamera3D::unproject_position(const Vector3 &p_pos) const {
return res;
};
-Vector3 XRCamera3D::project_position(const Point2 &p_point, float p_z_depth) const {
+Vector3 XRCamera3D::project_position(const Point2 &p_point, real_t p_z_depth) const {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, Vector3());
@@ -544,7 +544,7 @@ void XROrigin3D::clear_tracked_camera_if(XRCamera3D *p_tracked_camera) {
};
};
-float XROrigin3D::get_world_scale() const {
+real_t XROrigin3D::get_world_scale() const {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, 1.0);
@@ -552,7 +552,7 @@ float XROrigin3D::get_world_scale() const {
return xr_server->get_world_scale();
};
-void XROrigin3D::set_world_scale(float p_world_scale) {
+void XROrigin3D::set_world_scale(real_t p_world_scale) {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL(xr_server);
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index 90079f5fe9..312287a93b 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -54,7 +54,7 @@ public:
virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const override;
virtual Point2 unproject_position(const Vector3 &p_pos) const override;
- virtual Vector3 project_position(const Point2 &p_point, float p_z_depth) const override;
+ virtual Vector3 project_position(const Point2 &p_point, real_t p_z_depth) const override;
virtual Vector<Plane> get_frustum() const override;
XRCamera3D() {}
@@ -163,8 +163,8 @@ public:
void set_tracked_camera(XRCamera3D *p_tracked_camera);
void clear_tracked_camera_if(XRCamera3D *p_tracked_camera);
- float get_world_scale() const;
- void set_world_scale(float p_world_scale);
+ real_t get_world_scale() const;
+ void set_world_scale(real_t p_world_scale);
XROrigin3D() {}
~XROrigin3D() {}
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp
index 6e5d964b76..0167992baf 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -219,7 +219,7 @@ void AnimationNodeBlendSpace1D::_add_blend_point(int p_index, const Ref<Animatio
}
}
-float AnimationNodeBlendSpace1D::process(float p_time, bool p_seek) {
+double AnimationNodeBlendSpace1D::process(double p_time, bool p_seek) {
if (blend_points_used == 0) {
return 0.0;
}
@@ -229,7 +229,7 @@ float AnimationNodeBlendSpace1D::process(float p_time, bool p_seek) {
return blend_node(blend_points[0].name, blend_points[0].node, p_time, p_seek, 1.0, FILTER_IGNORE, false);
}
- float blend_pos = get_parameter(blend_position);
+ double blend_pos = get_parameter(blend_position);
float weights[MAX_BLEND_POINTS] = {};
diff --git a/scene/animation/animation_blend_space_1d.h b/scene/animation/animation_blend_space_1d.h
index 8886e6c679..6730c09fd4 100644
--- a/scene/animation/animation_blend_space_1d.h
+++ b/scene/animation/animation_blend_space_1d.h
@@ -93,7 +93,7 @@ public:
void set_value_label(const String &p_label);
String get_value_label() const;
- float process(float p_time, bool p_seek) override;
+ double process(double p_time, bool p_seek) override;
String get_caption() const override;
Ref<AnimationNode> get_child_by_name(const StringName &p_name) override;
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index d88a9badf4..145e7c605b 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -431,12 +431,12 @@ void AnimationNodeBlendSpace2D::_blend_triangle(const Vector2 &p_pos, const Vect
r_weights[2] = w;
}
-float AnimationNodeBlendSpace2D::process(float p_time, bool p_seek) {
+double AnimationNodeBlendSpace2D::process(double p_time, bool p_seek) {
_update_triangles();
Vector2 blend_pos = get_parameter(blend_position);
int closest = get_parameter(this->closest);
- float length_internal = get_parameter(this->length_internal);
+ double length_internal = get_parameter(this->length_internal);
float mind = 0.0; //time of min distance point
if (blend_mode == BLEND_MODE_INTERPOLATED) {
diff --git a/scene/animation/animation_blend_space_2d.h b/scene/animation/animation_blend_space_2d.h
index 65d09a550d..a919fff1d2 100644
--- a/scene/animation/animation_blend_space_2d.h
+++ b/scene/animation/animation_blend_space_2d.h
@@ -126,7 +126,7 @@ public:
void set_y_label(const String &p_label);
String get_y_label() const;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
virtual String get_caption() const override;
Vector2 get_closest_point(const Vector2 &p_point);
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 4bddae3b14..049f3483ff 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -63,11 +63,11 @@ void AnimationNodeAnimation::_validate_property(PropertyInfo &property) const {
}
}
-float AnimationNodeAnimation::process(float p_time, bool p_seek) {
+double AnimationNodeAnimation::process(double p_time, bool p_seek) {
AnimationPlayer *ap = state->player;
ERR_FAIL_COND_V(!ap, 0);
- float time = get_parameter(this->time);
+ double time = get_parameter(this->time);
if (!ap->has_animation(animation)) {
AnimationNodeBlendTree *tree = Object::cast_to<AnimationNodeBlendTree>(parent);
@@ -84,7 +84,7 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
Ref<Animation> anim = ap->get_animation(animation);
- float step;
+ double step;
if (p_seek) {
time = p_time;
@@ -94,7 +94,7 @@ float AnimationNodeAnimation::process(float p_time, bool p_seek) {
step = p_time;
}
- float anim_size = anim->get_length();
+ double anim_size = anim->get_length();
if (anim->has_loop()) {
if (anim_size) {
@@ -202,12 +202,12 @@ bool AnimationNodeOneShot::has_filter() const {
return true;
}
-float AnimationNodeOneShot::process(float p_time, bool p_seek) {
+double AnimationNodeOneShot::process(double p_time, bool p_seek) {
bool active = get_parameter(this->active);
bool prev_active = get_parameter(this->prev_active);
- float time = get_parameter(this->time);
- float remaining = get_parameter(this->remaining);
- float time_to_restart = get_parameter(this->time_to_restart);
+ double time = get_parameter(this->time);
+ double remaining = get_parameter(this->remaining);
+ double time_to_restart = get_parameter(this->time_to_restart);
if (!active) {
//make it as if this node doesn't exist, pass input 0 by.
@@ -370,9 +370,9 @@ bool AnimationNodeAdd2::has_filter() const {
return true;
}
-float AnimationNodeAdd2::process(float p_time, bool p_seek) {
- float amount = get_parameter(add_amount);
- float rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
+double AnimationNodeAdd2::process(double p_time, bool p_seek) {
+ double amount = get_parameter(add_amount);
+ double rem0 = blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync);
return rem0;
@@ -416,10 +416,10 @@ bool AnimationNodeAdd3::has_filter() const {
return true;
}
-float AnimationNodeAdd3::process(float p_time, bool p_seek) {
- float amount = get_parameter(add_amount);
+double AnimationNodeAdd3::process(double p_time, bool p_seek) {
+ double amount = get_parameter(add_amount);
blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_PASS, !sync);
- float rem0 = blend_input(1, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
+ double rem0 = blend_input(1, p_time, p_seek, 1.0, FILTER_IGNORE, !sync);
blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_PASS, !sync);
return rem0;
@@ -452,11 +452,11 @@ String AnimationNodeBlend2::get_caption() const {
return "Blend2";
}
-float AnimationNodeBlend2::process(float p_time, bool p_seek) {
- float amount = get_parameter(blend_amount);
+double AnimationNodeBlend2::process(double p_time, bool p_seek) {
+ double amount = get_parameter(blend_amount);
- float rem0 = blend_input(0, p_time, p_seek, 1.0 - amount, FILTER_BLEND, !sync);
- float rem1 = blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync);
+ double rem0 = blend_input(0, p_time, p_seek, 1.0 - amount, FILTER_BLEND, !sync);
+ double rem1 = blend_input(1, p_time, p_seek, amount, FILTER_PASS, !sync);
return amount > 0.5 ? rem1 : rem0; //hacky but good enough
}
@@ -507,11 +507,11 @@ bool AnimationNodeBlend3::is_using_sync() const {
return sync;
}
-float AnimationNodeBlend3::process(float p_time, bool p_seek) {
- float amount = get_parameter(blend_amount);
- float rem0 = blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_IGNORE, !sync);
- float rem1 = blend_input(1, p_time, p_seek, 1.0 - ABS(amount), FILTER_IGNORE, !sync);
- float rem2 = blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_IGNORE, !sync);
+double AnimationNodeBlend3::process(double p_time, bool p_seek) {
+ double amount = get_parameter(blend_amount);
+ double rem0 = blend_input(0, p_time, p_seek, MAX(0, -amount), FILTER_IGNORE, !sync);
+ double rem1 = blend_input(1, p_time, p_seek, 1.0 - ABS(amount), FILTER_IGNORE, !sync);
+ double rem2 = blend_input(2, p_time, p_seek, MAX(0, amount), FILTER_IGNORE, !sync);
return amount > 0.5 ? rem2 : (amount < -0.5 ? rem0 : rem1); //hacky but good enough
}
@@ -545,8 +545,8 @@ String AnimationNodeTimeScale::get_caption() const {
return "TimeScale";
}
-float AnimationNodeTimeScale::process(float p_time, bool p_seek) {
- float scale = get_parameter(this->scale);
+double AnimationNodeTimeScale::process(double p_time, bool p_seek) {
+ double scale = get_parameter(this->scale);
if (p_seek) {
return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false);
} else {
@@ -575,12 +575,12 @@ String AnimationNodeTimeSeek::get_caption() const {
return "Seek";
}
-float AnimationNodeTimeSeek::process(float p_time, bool p_seek) {
- float seek_pos = get_parameter(this->seek_pos);
+double AnimationNodeTimeSeek::process(double p_time, bool p_seek) {
+ double seek_pos = get_parameter(this->seek_pos);
if (p_seek) {
return blend_input(0, p_time, true, 1.0, FILTER_IGNORE, false);
} else if (seek_pos >= 0) {
- float ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false);
+ double ret = blend_input(0, seek_pos, true, 1.0, FILTER_IGNORE, false);
set_parameter(this->seek_pos, -1.0); //reset
return ret;
} else {
@@ -676,13 +676,13 @@ float AnimationNodeTransition::get_cross_fade_time() const {
return xfade;
}
-float AnimationNodeTransition::process(float p_time, bool p_seek) {
+double AnimationNodeTransition::process(double p_time, bool p_seek) {
int current = get_parameter(this->current);
int prev = get_parameter(this->prev);
int prev_current = get_parameter(this->prev_current);
- float time = get_parameter(this->time);
- float prev_xfading = get_parameter(this->prev_xfading);
+ double time = get_parameter(this->time);
+ double prev_xfading = get_parameter(this->prev_xfading);
bool switched = current != prev_current;
@@ -794,7 +794,7 @@ String AnimationNodeOutput::get_caption() const {
return "Output";
}
-float AnimationNodeOutput::process(float p_time, bool p_seek) {
+double AnimationNodeOutput::process(double p_time, bool p_seek) {
return blend_input(0, p_time, p_seek, 1.0);
}
@@ -1007,7 +1007,7 @@ String AnimationNodeBlendTree::get_caption() const {
return "BlendTree";
}
-float AnimationNodeBlendTree::process(float p_time, bool p_seek) {
+double AnimationNodeBlendTree::process(double p_time, bool p_seek) {
Ref<AnimationNodeOutput> output = nodes[SceneStringNames::get_singleton()->output].node;
return _blend_node("output", nodes[SceneStringNames::get_singleton()->output].connections, this, output, p_time, p_seek, 1.0);
}
diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h
index d82658c8c2..8508aaf71b 100644
--- a/scene/animation/animation_blend_tree.h
+++ b/scene/animation/animation_blend_tree.h
@@ -53,7 +53,7 @@ public:
static Vector<String> (*get_editable_animation_list)();
virtual String get_caption() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
void set_animation(const StringName &p_name);
StringName get_animation() const;
@@ -122,7 +122,7 @@ public:
bool is_using_sync() const;
virtual bool has_filter() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
AnimationNodeOneShot();
};
@@ -148,7 +148,7 @@ public:
bool is_using_sync() const;
virtual bool has_filter() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
AnimationNodeAdd2();
};
@@ -172,7 +172,7 @@ public:
bool is_using_sync() const;
virtual bool has_filter() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
AnimationNodeAdd3();
};
@@ -191,7 +191,7 @@ public:
virtual Variant get_parameter_default_value(const StringName &p_parameter) const override;
virtual String get_caption() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
void set_use_sync(bool p_sync);
bool is_using_sync() const;
@@ -218,7 +218,7 @@ public:
void set_use_sync(bool p_sync);
bool is_using_sync() const;
- float process(float p_time, bool p_seek) override;
+ double process(double p_time, bool p_seek) override;
AnimationNodeBlend3();
};
@@ -236,7 +236,7 @@ public:
virtual String get_caption() const override;
- float process(float p_time, bool p_seek) override;
+ double process(double p_time, bool p_seek) override;
AnimationNodeTimeScale();
};
@@ -255,7 +255,7 @@ public:
virtual String get_caption() const override;
- float process(float p_time, bool p_seek) override;
+ double process(double p_time, bool p_seek) override;
AnimationNodeTimeSeek();
};
@@ -313,7 +313,7 @@ public:
void set_cross_fade_time(float p_fade);
float get_cross_fade_time() const;
- float process(float p_time, bool p_seek) override;
+ double process(double p_time, bool p_seek) override;
AnimationNodeTransition();
};
@@ -323,7 +323,7 @@ class AnimationNodeOutput : public AnimationNode {
public:
virtual String get_caption() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
AnimationNodeOutput();
};
@@ -390,7 +390,7 @@ public:
void get_node_connections(List<NodeConnection> *r_connections) const;
virtual String get_caption() const override;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
void get_node_list(List<StringName> *r_list);
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index bf53b554bf..9fc1dbd0c6 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -286,7 +286,7 @@ bool AnimationNodeStateMachinePlayback::_travel(AnimationNodeStateMachine *p_sta
return true;
}
-float AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, float p_time, bool p_seek) {
+double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek) {
//if not playing and it can restart, then restart
if (!playing && start_request == StringName()) {
if (!stop_request && p_state_machine->start_node) {
@@ -790,7 +790,7 @@ Vector2 AnimationNodeStateMachine::get_graph_offset() const {
return graph_offset;
}
-float AnimationNodeStateMachine::process(float p_time, bool p_seek) {
+double AnimationNodeStateMachine::process(double p_time, bool p_seek) {
Ref<AnimationNodeStateMachinePlayback> playback = get_parameter(this->playback);
ERR_FAIL_COND_V(playback.is_null(), 0.0);
diff --git a/scene/animation/animation_node_state_machine.h b/scene/animation/animation_node_state_machine.h
index 9c1bca63c3..6f0e3107fd 100644
--- a/scene/animation/animation_node_state_machine.h
+++ b/scene/animation/animation_node_state_machine.h
@@ -114,7 +114,7 @@ class AnimationNodeStateMachinePlayback : public Resource {
bool _travel(AnimationNodeStateMachine *p_state_machine, const StringName &p_travel);
- float process(AnimationNodeStateMachine *p_state_machine, float p_time, bool p_seek);
+ double process(AnimationNodeStateMachine *p_state_machine, double p_time, bool p_seek);
protected:
static void _bind_methods();
@@ -210,7 +210,7 @@ public:
void set_graph_offset(const Vector2 &p_offset);
Vector2 get_graph_offset() const;
- virtual float process(float p_time, bool p_seek) override;
+ virtual double process(double p_time, bool p_seek) override;
virtual String get_caption() const override;
virtual Ref<AnimationNode> get_child_by_name(const StringName &p_name) override;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 67b6205a65..5d200ebf86 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -341,7 +341,7 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
}
}
-void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) {
+void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -723,7 +723,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
continue;
}
- float pos = a->track_get_key_time(i, idx);
+ double pos = a->track_get_key_time(i, idx);
StringName anim_name = a->animation_track_get_key_animation(i, idx);
if (String(anim_name) == "[stop]" || !player->has_animation(anim_name)) {
@@ -732,12 +732,12 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
Ref<Animation> anim = player->get_animation(anim_name);
- float at_anim_pos;
+ double at_anim_pos;
if (anim->has_loop()) {
- at_anim_pos = Math::fposmod(p_time - pos, anim->get_length()); //seek to loop
+ at_anim_pos = Math::fposmod(p_time - pos, (double)anim->get_length()); //seek to loop
} else {
- at_anim_pos = MAX(anim->get_length(), p_time - pos); //seek to end
+ at_anim_pos = MAX((double)anim->get_length(), p_time - pos); //seek to end
}
if (player->is_playing() || p_seeked) {
@@ -776,11 +776,11 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
}
}
-void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started) {
- float delta = p_delta * speed_scale * cd.speed_scale;
- float next_pos = cd.pos + delta;
+void AnimationPlayer::_animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started) {
+ double delta = p_delta * speed_scale * cd.speed_scale;
+ double next_pos = cd.pos + delta;
- float len = cd.from->animation->get_length();
+ real_t len = cd.from->animation->get_length();
bool loop = cd.from->animation->has_loop();
if (!loop) {
@@ -808,7 +808,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f
}
} else {
- float looped_next_pos = Math::fposmod(next_pos, len);
+ double looped_next_pos = Math::fposmod(next_pos, (double)len);
if (looped_next_pos == 0 && next_pos != 0) {
// Loop multiples of the length to it, rather than 0
// so state at time=length is previewable in the editor
@@ -823,7 +823,7 @@ void AnimationPlayer::_animation_process_data(PlaybackData &cd, float p_delta, f
_animation_process_animation(cd.from, cd.pos, delta, p_blend, &cd == &playback.current, p_seeked, p_started);
}
-void AnimationPlayer::_animation_process2(float p_delta, bool p_started) {
+void AnimationPlayer::_animation_process2(double p_delta, bool p_started) {
Playback &c = playback;
accum_pass++;
@@ -927,7 +927,7 @@ void AnimationPlayer::_animation_update_transforms() {
cache_update_bezier_size = 0;
}
-void AnimationPlayer::_animation_process(float p_delta) {
+void AnimationPlayer::_animation_process(double p_delta) {
if (playback.current.from) {
end_reached = false;
end_notify = false;
@@ -1283,7 +1283,7 @@ float AnimationPlayer::get_playing_speed() const {
return speed_scale * playback.current.speed_scale;
}
-void AnimationPlayer::seek(float p_time, bool p_update) {
+void AnimationPlayer::seek(double p_time, bool p_update) {
if (!playback.current.from) {
if (playback.assigned) {
ERR_FAIL_COND(!animation_set.has(playback.assigned));
@@ -1299,7 +1299,7 @@ void AnimationPlayer::seek(float p_time, bool p_update) {
}
}
-void AnimationPlayer::seek_delta(float p_time, float p_delta) {
+void AnimationPlayer::seek_delta(double p_time, float p_delta) {
if (!playback.current.from) {
if (playback.assigned) {
ERR_FAIL_COND(!animation_set.has(playback.assigned));
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 7cd9de1fa1..b693e29bdf 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -215,13 +215,13 @@ private:
NodePath root;
- void _animation_process_animation(AnimationData *p_anim, float p_time, float p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false);
+ void _animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current = true, bool p_seeked = false, bool p_started = false);
void _ensure_node_caches(AnimationData *p_anim, Node *p_root_override = nullptr);
- void _animation_process_data(PlaybackData &cd, float p_delta, float p_blend, bool p_seeked, bool p_started);
- void _animation_process2(float p_delta, bool p_started);
+ void _animation_process_data(PlaybackData &cd, double p_delta, float p_blend, bool p_seeked, bool p_started);
+ void _animation_process2(double p_delta, bool p_started);
void _animation_update_transforms();
- void _animation_process(float p_delta);
+ void _animation_process(double p_delta);
void _node_removed(Node *p_node);
void _stop_playing_caches();
@@ -306,8 +306,8 @@ public:
void set_method_call_mode(AnimationMethodCallMode p_mode);
AnimationMethodCallMode get_method_call_mode() const;
- void seek(float p_time, bool p_update = false);
- void seek_delta(float p_time, float p_delta);
+ void seek(double p_time, bool p_update = false);
+ void seek_delta(double p_time, float p_delta);
float get_current_animation_position() const;
float get_current_animation_length() const;
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index e623309888..543545b90f 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -85,7 +85,7 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
}
}
-void AnimationNode::blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend) {
+void AnimationNode::blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend) {
ERR_FAIL_COND(!state);
ERR_FAIL_COND(!state->player->has_animation(p_animation));
@@ -115,13 +115,13 @@ void AnimationNode::blend_animation(const StringName &p_animation, float p_time,
state->animation_states.push_back(anim_state);
}
-float AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections) {
+real_t AnimationNode::_pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, real_t p_time, bool p_seek, const Vector<StringName> &p_connections) {
base_path = p_base_path;
parent = p_parent;
connections = p_connections;
state = p_state;
- float t = process(p_time, p_seek);
+ real_t t = process(p_time, p_seek);
state = nullptr;
parent = nullptr;
@@ -140,7 +140,7 @@ void AnimationNode::make_invalid(const String &p_reason) {
state->invalid_reasons += String::utf8("• ") + p_reason;
}
-float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
+real_t AnimationNode::blend_input(int p_input, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize) {
ERR_FAIL_INDEX_V(p_input, inputs.size(), 0);
ERR_FAIL_COND_V(!state, 0);
@@ -158,8 +158,8 @@ float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p
Ref<AnimationNode> node = blend_tree->get_node(node_name);
//inputs.write[p_input].last_pass = state->last_pass;
- float activity = 0.0;
- float ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
+ real_t activity = 0.0;
+ real_t ret = _blend_node(node_name, blend_tree->get_node_connection_array(node_name), nullptr, node, p_time, p_seek, p_blend, p_filter, p_optimize, &activity);
Vector<AnimationTree::Activity> *activity_ptr = state->tree->input_activity_map.getptr(base_path);
@@ -170,11 +170,11 @@ float AnimationNode::blend_input(int p_input, float p_time, bool p_seek, float p
return ret;
}
-float AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize) {
+real_t AnimationNode::blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize) {
return _blend_node(p_sub_path, Vector<StringName>(), this, p_node, p_time, p_seek, p_blend, p_filter, p_optimize);
}
-float AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter, bool p_optimize, float *r_max) {
+real_t AnimationNode::_blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter, bool p_optimize, real_t *r_max) {
ERR_FAIL_COND_V(!p_node.is_valid(), 0);
ERR_FAIL_COND_V(!state, 0);
@@ -184,8 +184,8 @@ float AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Strin
p_node->blends.resize(blend_count);
}
- float *blendw = p_node->blends.ptrw();
- const float *blendr = blends.ptr();
+ real_t *blendw = p_node->blends.ptrw();
+ const real_t *blendr = blends.ptr();
bool any_valid = false;
@@ -328,7 +328,7 @@ void AnimationNode::remove_input(int p_index) {
emit_changed();
}
-float AnimationNode::process(float p_time, bool p_seek) {
+double AnimationNode::process(double p_time, bool p_seek) {
if (get_script_instance()) {
return get_script_instance()->call("_process", p_time, p_seek);
}
@@ -718,7 +718,7 @@ void AnimationTree::_clear_caches() {
cache_valid = false;
}
-void AnimationTree::_process_graph(float p_delta) {
+void AnimationTree::_process_graph(real_t p_delta) {
_update_properties(); //if properties need updating, update them
//check all tracks, see if they need modification
@@ -790,7 +790,7 @@ void AnimationTree::_process_graph(float p_delta) {
// root source blends
root->blends.resize(state.track_count);
- float *src_blendsw = root->blends.ptrw();
+ real_t *src_blendsw = root->blends.ptrw();
for (int i = 0; i < state.track_count; i++) {
src_blendsw[i] = 1.0; //by default all go to 1 for the root input
}
@@ -818,9 +818,9 @@ void AnimationTree::_process_graph(float p_delta) {
for (const AnimationNode::AnimationState &as : state.animation_states) {
Ref<Animation> a = as.animation;
- float time = as.time;
- float delta = as.delta;
- float weight = as.blend;
+ double time = as.time;
+ double delta = as.delta;
+ real_t weight = as.blend;
bool seeked = as.seeked;
for (int i = 0; i < a->get_track_count(); i++) {
@@ -840,7 +840,7 @@ void AnimationTree::_process_graph(float p_delta) {
ERR_CONTINUE(blend_idx < 0 || blend_idx >= state.track_count);
- float blend = (*as.track_blends)[blend_idx] * weight;
+ real_t blend = (*as.track_blends)[blend_idx] * weight;
if (blend < CMP_EPSILON) {
continue; //nothing to blend
@@ -860,7 +860,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->scale = Vector3(1, 1, 1);
}
- float prev_time = time - delta;
+ real_t prev_time = time - delta;
if (prev_time < 0) {
if (!a->has_loop()) {
prev_time = 0;
@@ -928,7 +928,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->rot = rot;
t->rot_blend_accum = blend;
} else {
- float rot_total = t->rot_blend_accum + blend;
+ real_t rot_total = t->rot_blend_accum + blend;
t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
t->rot_blend_accum = rot_total;
}
@@ -1003,7 +1003,7 @@ void AnimationTree::_process_graph(float p_delta) {
case Animation::TYPE_BEZIER: {
TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
- float bezier = a->bezier_track_interpolate(i, time);
+ real_t bezier = a->bezier_track_interpolate(i, time);
if (t->process_pass != process_pass) {
t->value = bezier;
@@ -1029,10 +1029,10 @@ void AnimationTree::_process_graph(float p_delta) {
t->playing = false;
playing_caches.erase(t);
} else {
- float start_ofs = a->audio_track_get_key_start_offset(i, idx);
+ real_t start_ofs = a->audio_track_get_key_start_offset(i, idx);
start_ofs += time - a->track_get_key_time(i, idx);
- float end_ofs = a->audio_track_get_key_end_offset(i, idx);
- float len = stream->get_length();
+ real_t end_ofs = a->audio_track_get_key_end_offset(i, idx);
+ real_t len = stream->get_length();
if (start_ofs > len - end_ofs) {
t->object->call("stop");
@@ -1068,9 +1068,9 @@ void AnimationTree::_process_graph(float p_delta) {
t->playing = false;
playing_caches.erase(t);
} else {
- float start_ofs = a->audio_track_get_key_start_offset(i, idx);
- float end_ofs = a->audio_track_get_key_end_offset(i, idx);
- float len = stream->get_length();
+ real_t start_ofs = a->audio_track_get_key_start_offset(i, idx);
+ real_t end_ofs = a->audio_track_get_key_end_offset(i, idx);
+ real_t len = stream->get_length();
t->object->call("set_stream", stream);
t->object->call("play", start_ofs);
@@ -1093,7 +1093,7 @@ void AnimationTree::_process_graph(float p_delta) {
if (!loop && time < t->start) {
stop = true;
} else if (t->len > 0) {
- float len = t->start > time ? (a->get_length() - t->start) + time : time - t->start;
+ real_t len = t->start > time ? (a->get_length() - t->start) + time : time - t->start;
if (len > t->len) {
stop = true;
@@ -1109,7 +1109,7 @@ void AnimationTree::_process_graph(float p_delta) {
}
}
- float db = Math::linear2db(MAX(blend, 0.00001));
+ real_t db = Math::linear2db(MAX(blend, 0.00001));
if (t->object->has_method("set_unit_db")) {
t->object->call("set_unit_db", db);
} else {
@@ -1132,7 +1132,7 @@ void AnimationTree::_process_graph(float p_delta) {
continue;
}
- float pos = a->track_get_key_time(i, idx);
+ double pos = a->track_get_key_time(i, idx);
StringName anim_name = a->animation_track_get_key_animation(i, idx);
if (String(anim_name) == "[stop]" || !player2->has_animation(anim_name)) {
@@ -1141,10 +1141,10 @@ void AnimationTree::_process_graph(float p_delta) {
Ref<Animation> anim = player2->get_animation(anim_name);
- float at_anim_pos;
+ real_t at_anim_pos;
if (anim->has_loop()) {
- at_anim_pos = Math::fposmod(time - pos, anim->get_length()); //seek to loop
+ at_anim_pos = Math::fposmod(time - pos, (double)anim->get_length()); //seek to loop
} else {
at_anim_pos = MAX(anim->get_length(), time - pos); //seek to end
}
@@ -1238,7 +1238,7 @@ void AnimationTree::_process_graph(float p_delta) {
}
}
-void AnimationTree::advance(float p_time) {
+void AnimationTree::advance(real_t p_time) {
_process_graph(p_time);
}
@@ -1443,7 +1443,7 @@ void AnimationTree::rename_parameter(const String &p_base, const String &p_new_b
_update_properties();
}
-float AnimationTree::get_connection_activity(const StringName &p_path, int p_connection) const {
+real_t AnimationTree::get_connection_activity(const StringName &p_path, int p_connection) const {
if (!input_activity_map_get.has(p_path)) {
return 0;
}
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 60e0c7200a..59bbc5b4da 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -57,16 +57,16 @@ public:
Vector<Input> inputs;
- float process_input(int p_input, float p_time, bool p_seek, float p_blend);
+ real_t process_input(int p_input, real_t p_time, bool p_seek, real_t p_blend);
friend class AnimationTree;
struct AnimationState {
Ref<Animation> animation;
- float time = 0.0;
- float delta = 0.0;
- const Vector<float> *track_blends = nullptr;
- float blend = 0.0;
+ double time = 0.0;
+ double delta = 0.0;
+ const Vector<real_t> *track_blends = nullptr;
+ real_t blend = 0.0;
bool seeked = false;
};
@@ -81,10 +81,10 @@ public:
uint64_t last_pass = 0;
};
- Vector<float> blends;
+ Vector<real_t> blends;
State *state = nullptr;
- float _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, float p_time, bool p_seek, const Vector<StringName> &p_connections);
+ real_t _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, real_t p_time, bool p_seek, const Vector<StringName> &p_connections);
void _pre_update_animations(HashMap<NodePath, int> *track_map);
//all this is temporary
@@ -98,12 +98,12 @@ public:
Array _get_filters() const;
void _set_filters(const Array &p_filters);
friend class AnimationNodeBlendTree;
- float _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, float *r_max = nullptr);
+ real_t _blend_node(const StringName &p_subpath, const Vector<StringName> &p_connections, AnimationNode *p_new_parent, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true, real_t *r_max = nullptr);
protected:
- void blend_animation(const StringName &p_animation, float p_time, float p_delta, bool p_seeked, float p_blend);
- float blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
- float blend_input(int p_input, float p_time, bool p_seek, float p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
+ void blend_animation(const StringName &p_animation, real_t p_time, real_t p_delta, bool p_seeked, real_t p_blend);
+ real_t blend_node(const StringName &p_sub_path, Ref<AnimationNode> p_node, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
+ real_t blend_input(int p_input, real_t p_time, bool p_seek, real_t p_blend, FilterAction p_filter = FILTER_IGNORE, bool p_optimize = true);
void make_invalid(const String &p_reason);
static void _bind_methods();
@@ -126,7 +126,7 @@ public:
virtual void get_child_nodes(List<ChildNode> *r_child_nodes);
- virtual float process(float p_time, bool p_seek);
+ virtual double process(double p_time, bool p_seek);
virtual String get_caption() const;
int get_input_count() const;
@@ -191,7 +191,7 @@ private:
int bone_idx = -1;
Vector3 loc;
Quaternion rot;
- float rot_blend_accum = 0.0;
+ real_t rot_blend_accum = 0.0;
Vector3 scale;
TrackCacheTransform() {
@@ -210,7 +210,7 @@ private:
};
struct TrackCacheBezier : public TrackCache {
- float value = 0.0;
+ real_t value = 0.0;
Vector<StringName> subpath;
TrackCacheBezier() {
type = Animation::TYPE_BEZIER;
@@ -219,8 +219,8 @@ private:
struct TrackCacheAudio : public TrackCache {
bool playing = false;
- float start = 0.0;
- float len = 0.0;
+ real_t start = 0.0;
+ real_t len = 0.0;
TrackCacheAudio() {
type = Animation::TYPE_AUDIO;
@@ -251,7 +251,7 @@ private:
void _clear_caches();
bool _update_caches(AnimationPlayer *player);
- void _process_graph(float p_delta);
+ void _process_graph(real_t p_delta);
uint64_t setup_pass = 1;
uint64_t process_pass = 1;
@@ -271,7 +271,7 @@ private:
struct Activity {
uint64_t last_pass = 0;
- float activity = 0.0;
+ real_t activity = 0.0;
};
HashMap<StringName, Vector<Activity>> input_activity_map;
@@ -312,8 +312,8 @@ public:
Transform3D get_root_motion_transform() const;
- float get_connection_activity(const StringName &p_path, int p_connection) const;
- void advance(float p_time);
+ real_t get_connection_activity(const StringName &p_path, int p_connection) const;
+ void advance(real_t p_time);
void rename_parameter(const String &p_base, const String &p_new_base);
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index 55fd2d2b73..d64c8bc675 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -39,8 +39,8 @@ class RootMotionView : public VisualInstance3D {
public:
Ref<ImmediateMesh> immediate;
NodePath path;
- float cell_size = 1.0;
- float radius = 10.0;
+ real_t cell_size = 1.0;
+ real_t radius = 10.0;
bool use_in_game = false;
Color color = Color(0.5, 0.5, 1.0);
bool first = true;
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index ce2b320c96..869f2f68f7 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -94,7 +94,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
} else if (p_msg == "override_camera_3D:set") {
ERR_FAIL_COND_V(p_args.size() < 1, ERR_INVALID_DATA);
bool enable = p_args[0];
- scene_tree->get_root()->enable_camera_override(enable);
+ scene_tree->get_root()->enable_camera_3d_override(enable);
} else if (p_msg == "override_camera_3D:transform") {
ERR_FAIL_COND_V(p_args.size() < 5, ERR_INVALID_DATA);
@@ -104,11 +104,11 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
float near = p_args[3];
float far = p_args[4];
if (is_perspective) {
- scene_tree->get_root()->set_camera_override_perspective(size_or_fov, near, far);
+ scene_tree->get_root()->set_camera_3d_override_perspective(size_or_fov, near, far);
} else {
- scene_tree->get_root()->set_camera_override_orthogonal(size_or_fov, near, far);
+ scene_tree->get_root()->set_camera_3d_override_orthogonal(size_or_fov, near, far);
}
- scene_tree->get_root()->set_camera_override_transform(transform);
+ scene_tree->get_root()->set_camera_3d_override_transform(transform);
} else if (p_msg == "set_object_property") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 82f4a216b8..871ad889ca 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -145,6 +145,9 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
if (status.press_attempt && status.pressing_inside) {
if (toggle_mode) {
+ if (Object::cast_to<InputEventShortcut>(*p_event)) {
+ action_mode = ACTION_MODE_BUTTON_PRESS; // HACK.
+ }
if ((p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_PRESS) || (!p_event->is_pressed() && action_mode == ACTION_MODE_BUTTON_RELEASE)) {
if (action_mode == ACTION_MODE_BUTTON_PRESS) {
status.press_attempt = false;
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 83ecf1d534..635f3c51b9 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -49,9 +49,6 @@ GradientEdit::GradientEdit() {
popup->add_child(picker);
add_child(popup);
-
- checker = Ref<ImageTexture>(memnew(ImageTexture));
- Ref<Image> img = memnew(Image(checker_bg_png));
}
int GradientEdit::_get_point_from_pos(int x) {
@@ -311,7 +308,7 @@ void GradientEdit::_notification(int p_what) {
int total_w = get_size().width - get_size().height - SPACING;
//Draw checker pattern for ramp
- _draw_checker(0, 0, total_w, h);
+ draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true);
//Draw color ramp
Gradient::Point prev;
@@ -378,7 +375,7 @@ void GradientEdit::_notification(int p_what) {
}
//Draw "button" for color selector
- _draw_checker(total_w + SPACING, 0, h, h);
+ draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + SPACING, 0, h, h), true);
if (grabbed != -1) {
//Draw with selection color
draw_rect(Rect2(total_w + SPACING, 0, h, h), points[grabbed].color);
@@ -405,27 +402,6 @@ void GradientEdit::_notification(int p_what) {
}
}
-void GradientEdit::_draw_checker(int x, int y, int w, int h) {
- //Draw it with polygon to insert UVs for scale
- Vector<Vector2> backPoints;
- backPoints.push_back(Vector2(x, y));
- backPoints.push_back(Vector2(x, y + h));
- backPoints.push_back(Vector2(x + w, y + h));
- backPoints.push_back(Vector2(x + w, y));
- Vector<Color> colorPoints;
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- Vector<Vector2> uvPoints;
- //Draw checker pattern pixel-perfect and scale it by 2.
- uvPoints.push_back(Vector2(x, y));
- uvPoints.push_back(Vector2(x, y + h * .5f / checker->get_height()));
- uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y + h * .5f / checker->get_height()));
- uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y));
- draw_polygon(backPoints, colorPoints, uvPoints, checker);
-}
-
Size2 GradientEdit::get_minimum_size() const {
return Vector2(0, 16);
}
@@ -439,7 +415,7 @@ void GradientEdit::_color_changed(const Color &p_color) {
emit_signal(SNAME("ramp_changed"));
}
-void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors) {
+void GradientEdit::set_ramp(const Vector<real_t> &p_offsets, const Vector<Color> &p_colors) {
ERR_FAIL_COND(p_offsets.size() != p_colors.size());
points.clear();
for (int i = 0; i < p_offsets.size(); i++) {
@@ -453,8 +429,8 @@ void GradientEdit::set_ramp(const Vector<float> &p_offsets, const Vector<Color>
update();
}
-Vector<float> GradientEdit::get_offsets() const {
- Vector<float> ret;
+Vector<real_t> GradientEdit::get_offsets() const {
+ Vector<real_t> ret;
for (int i = 0; i < points.size(); i++) {
ret.push_back(points[i].offset);
}
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index eb7367d598..b0ee2c4abb 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -42,8 +42,6 @@ class GradientEdit : public Control {
PopupPanel *popup;
ColorPicker *picker;
- Ref<ImageTexture> checker;
-
bool grabbing = false;
int grabbed = -1;
Vector<Gradient::Point> points;
@@ -59,8 +57,8 @@ protected:
static void _bind_methods();
public:
- void set_ramp(const Vector<float> &p_offsets, const Vector<Color> &p_colors);
- Vector<float> get_offsets() const;
+ void set_ramp(const Vector<real_t> &p_offsets, const Vector<Color> &p_colors);
+ Vector<real_t> get_offsets() const;
Vector<Color> get_colors() const;
void set_points(Vector<Gradient::Point> &p_points);
Vector<Gradient::Point> &get_points();
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index cf1f41d0fc..63b5793b3e 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -44,7 +44,7 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
return;
}
- if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
+ if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event) || Object::cast_to<InputEventShortcut>(*p_event))) {
if (!get_parent() || !is_visible_in_tree() || is_disabled()) {
return;
}
diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h
index d809fd502f..67323e7f93 100644
--- a/scene/gui/rich_text_effect.h
+++ b/scene/gui/rich_text_effect.h
@@ -59,7 +59,7 @@ public:
bool outline = false;
Point2 offset;
Color color;
- float elapsed_time = 0.0f;
+ double elapsed_time = 0.0f;
Dictionary environment;
uint32_t glpyh_index = 0;
RID font;
@@ -69,8 +69,8 @@ public:
Vector2i get_range() { return range; }
void set_range(const Vector2i &p_range) { range = p_range; }
- float get_elapsed_time() { return elapsed_time; }
- void set_elapsed_time(float p_elapsed_time) { elapsed_time = p_elapsed_time; }
+ double get_elapsed_time() { return elapsed_time; }
+ void set_elapsed_time(double p_elapsed_time) { elapsed_time = p_elapsed_time; }
bool is_visible() { return visibility; }
void set_visibility(bool p_visibility) { visibility = p_visibility; }
bool is_outline() { return outline; }
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 3925e0c38e..cf2a1481a1 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1323,7 +1323,7 @@ void RichTextLabel::_update_scroll() {
}
}
-void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, float p_delta_time) {
+void RichTextLabel::_update_fx(RichTextLabel::ItemFrame *p_frame, double p_delta_time) {
Item *it = p_frame;
while (it) {
ItemFX *ifx = nullptr;
@@ -1441,7 +1441,7 @@ void RichTextLabel::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
if (is_visible_in_tree()) {
- float dt = get_process_delta_time();
+ double dt = get_process_delta_time();
_update_fx(main, dt);
update();
}
@@ -2289,7 +2289,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
}
}
-void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, VAlign p_align) {
+void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlign p_align) {
if (current->type == ITEM_TABLE) {
return;
}
@@ -2534,7 +2534,7 @@ void RichTextLabel::push_meta(const Variant &p_meta) {
_add_item(item, true);
}
-void RichTextLabel::push_table(int p_columns, VAlign p_align) {
+void RichTextLabel::push_table(int p_columns, InlineAlign p_align) {
ERR_FAIL_COND(p_columns < 1);
ItemTable *item = memnew(ItemTable);
@@ -2897,18 +2897,35 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
columns = 1;
}
- VAlign align = VALIGN_TOP;
- if (subtag.size() > 1) {
+ int align = INLINE_ALIGN_TOP;
+ if (subtag.size() > 2) {
if (subtag[1] == "top" || subtag[1] == "t") {
- align = VALIGN_TOP;
+ align = INLINE_ALIGN_TOP_TO;
} else if (subtag[1] == "center" || subtag[1] == "c") {
- align = VALIGN_CENTER;
+ align = INLINE_ALIGN_CENTER_TO;
} else if (subtag[1] == "bottom" || subtag[1] == "b") {
- align = VALIGN_BOTTOM;
+ align = INLINE_ALIGN_BOTTOM_TO;
+ }
+ if (subtag[2] == "top" || subtag[2] == "t") {
+ align |= INLINE_ALIGN_TO_TOP;
+ } else if (subtag[2] == "center" || subtag[2] == "c") {
+ align |= INLINE_ALIGN_TO_CENTER;
+ } else if (subtag[2] == "baseline" || subtag[2] == "l") {
+ align |= INLINE_ALIGN_TO_BASELINE;
+ } else if (subtag[2] == "bottom" || subtag[2] == "b") {
+ align |= INLINE_ALIGN_TO_BOTTOM;
+ }
+ } else if (subtag.size() > 1) {
+ if (subtag[1] == "top" || subtag[1] == "t") {
+ align = INLINE_ALIGN_TOP;
+ } else if (subtag[1] == "center" || subtag[1] == "c") {
+ align = INLINE_ALIGN_CENTER;
+ } else if (subtag[1] == "bottom" || subtag[1] == "b") {
+ align = INLINE_ALIGN_BOTTOM;
}
}
- push_table(columns, align);
+ push_table(columns, (InlineAlign)align);
pos = brk_end + 1;
tag_stack.push_front("table");
} else if (tag == "cell") {
@@ -3187,15 +3204,34 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
pos = end;
tag_stack.push_front(bbcode_name);
} else if (tag.begins_with("img")) {
- VAlign align = VALIGN_TOP;
+ int align = INLINE_ALIGN_CENTER;
if (tag.begins_with("img=")) {
- String al = tag.substr(4, tag.length());
- if (al == "top" || al == "t") {
- align = VALIGN_TOP;
- } else if (al == "center" || al == "c") {
- align = VALIGN_CENTER;
- } else if (al == "bottom" || al == "b") {
- align = VALIGN_BOTTOM;
+ Vector<String> subtag = tag.substr(4, tag.length()).split(",");
+ if (subtag.size() > 1) {
+ if (subtag[0] == "top" || subtag[0] == "t") {
+ align = INLINE_ALIGN_TOP_TO;
+ } else if (subtag[0] == "center" || subtag[0] == "c") {
+ align = INLINE_ALIGN_CENTER_TO;
+ } else if (subtag[0] == "bottom" || subtag[0] == "b") {
+ align = INLINE_ALIGN_BOTTOM_TO;
+ }
+ if (subtag[1] == "top" || subtag[1] == "t") {
+ align |= INLINE_ALIGN_TO_TOP;
+ } else if (subtag[1] == "center" || subtag[1] == "c") {
+ align |= INLINE_ALIGN_TO_CENTER;
+ } else if (subtag[1] == "baseline" || subtag[1] == "l") {
+ align |= INLINE_ALIGN_TO_BASELINE;
+ } else if (subtag[1] == "bottom" || subtag[1] == "b") {
+ align |= INLINE_ALIGN_TO_BOTTOM;
+ }
+ } else if (subtag.size() > 0) {
+ if (subtag[0] == "top" || subtag[0] == "t") {
+ align = INLINE_ALIGN_TOP;
+ } else if (subtag[0] == "center" || subtag[0] == "c") {
+ align = INLINE_ALIGN_CENTER;
+ } else if (subtag[0] == "bottom" || subtag[0] == "b") {
+ align = INLINE_ALIGN_BOTTOM;
+ }
}
}
@@ -3236,7 +3272,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
}
}
- add_image(texture, width, height, color, align);
+ add_image(texture, width, height, color, (InlineAlign)align);
}
pos = end;
@@ -3961,7 +3997,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text);
ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
- ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(VALIGN_TOP));
+ ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);
@@ -3981,7 +4017,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline);
ClassDB::bind_method(D_METHOD("push_strikethrough"), &RichTextLabel::push_strikethrough);
- ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align"), &RichTextLabel::push_table, DEFVAL(VALIGN_TOP));
+ ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align"), &RichTextLabel::push_table, DEFVAL(INLINE_ALIGN_TOP));
ClassDB::bind_method(D_METHOD("push_dropcap", "string", "font", "size", "dropcap_margins", "color", "outline_size", "outline_color"), &RichTextLabel::push_dropcap, DEFVAL(Rect2()), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(0, 0, 0, 0)));
ClassDB::bind_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand);
ClassDB::bind_method(D_METHOD("set_cell_row_background_color", "odd_row_bg", "even_row_bg"), &RichTextLabel::set_cell_row_background_color);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 999d8b05fd..28dfe74b08 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -161,7 +161,7 @@ private:
struct ItemImage : public Item {
Ref<Texture2D> image;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_CENTER;
Size2 size;
Color color;
ItemImage() { type = ITEM_IMAGE; }
@@ -248,7 +248,7 @@ private:
int total_width = 0;
int total_height = 0;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_TOP;
ItemTable() { type = ITEM_TABLE; }
};
@@ -260,7 +260,7 @@ private:
};
struct ItemFX : public Item {
- float elapsed_time = 0.f;
+ double elapsed_time = 0.f;
};
struct ItemShake : public ItemFX {
@@ -440,7 +440,7 @@ private:
void _fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack);
void _update_scroll();
- void _update_fx(ItemFrame *p_frame, float p_delta_time);
+ void _update_fx(ItemFrame *p_frame, double p_delta_time);
void _scroll_changed(double);
void _gui_input(Ref<InputEvent> p_event);
@@ -463,7 +463,7 @@ private:
public:
String get_text();
void add_text(const String &p_text);
- void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), VAlign p_align = VALIGN_TOP);
+ void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlign p_align = INLINE_ALIGN_CENTER);
void add_newline();
bool remove_line(const int p_line);
void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0));
@@ -484,7 +484,7 @@ public:
void push_indent(int p_level);
void push_list(int p_level, ListType p_list, bool p_capitalize);
void push_meta(const Variant &p_meta);
- void push_table(int p_columns, VAlign p_align = VALIGN_TOP);
+ void push_table(int p_columns, InlineAlign p_align = INLINE_ALIGN_TOP);
void push_fade(int p_start_index, int p_length);
void push_shake(int p_strength, float p_rate);
void push_wave(float p_frequency, float p_amplitude);
diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp
index 885a51e058..1c29870682 100644
--- a/scene/gui/shortcut.cpp
+++ b/scene/gui/shortcut.cpp
@@ -29,10 +29,10 @@
/*************************************************************************/
#include "shortcut.h"
-
#include "core/os/keyboard.h"
void Shortcut::set_event(const Ref<InputEvent> &p_event) {
+ ERR_FAIL_COND(Object::cast_to<InputEventShortcut>(*p_event));
event = p_event;
emit_changed();
}
@@ -42,6 +42,12 @@ Ref<InputEvent> Shortcut::get_event() const {
}
bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
+ Ref<InputEventShortcut> ies = p_event;
+ if (ies != nullptr) {
+ if (ies->get_shortcut().ptr() == this) {
+ return true;
+ }
+ }
return event.is_valid() && event->is_match(p_event, true);
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index f1e5574351..cbd5fa7425 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -116,6 +116,9 @@ void Node::_notification(int p_notification) {
memdelete(data.path_cache);
data.path_cache = nullptr;
}
+ if (data.filename.length()) {
+ get_multiplayer()->scene_enter_exit_notify(data.filename, this, false);
+ }
} break;
case NOTIFICATION_PATH_CHANGED: {
if (data.path_cache) {
@@ -147,6 +150,10 @@ void Node::_notification(int p_notification) {
get_script_instance()->call(SceneStringNames::get_singleton()->_ready);
}
+ if (data.filename.length()) {
+ ERR_FAIL_COND(!is_inside_tree());
+ get_multiplayer()->scene_enter_exit_notify(data.filename, this, true);
+ }
} break;
case NOTIFICATION_POSTINITIALIZE: {
@@ -705,7 +712,7 @@ bool Node::is_enabled() const {
return _is_enabled();
}
-float Node::get_physics_process_delta_time() const {
+double Node::get_physics_process_delta_time() const {
if (data.tree) {
return data.tree->get_physics_process_time();
} else {
@@ -713,7 +720,7 @@ float Node::get_physics_process_delta_time() const {
}
}
-float Node::get_process_delta_time() const {
+double Node::get_process_delta_time() const {
if (data.tree) {
return data.tree->get_process_time();
} else {
diff --git a/scene/main/node.h b/scene/main/node.h
index 0a88553ea1..9997f4e055 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -202,6 +202,7 @@ protected:
static String _get_name_num_separator();
friend class SceneState;
+ friend class MultiplayerAPI;
void _add_child_nocheck(Node *p_child, const StringName &p_name);
void _set_owner_nocheck(Node *p_owner);
@@ -339,11 +340,11 @@ public:
/* PROCESSING */
void set_physics_process(bool p_process);
- float get_physics_process_delta_time() const;
+ double get_physics_process_delta_time() const;
bool is_physics_processing() const;
void set_process(bool p_process);
- float get_process_delta_time() const;
+ double get_process_delta_time() const;
bool is_processing() const;
void set_physics_process_internal(bool p_process_internal);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index dcbbebbc55..420516cbcd 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1341,7 +1341,7 @@ SceneTree::SceneTree() {
set_multiplayer(Ref<MultiplayerAPI>(memnew(MultiplayerAPI)));
//root->set_world_2d( Ref<World2D>( memnew( World2D )));
- root->set_as_audio_listener(true);
+ root->set_as_audio_listener_3d(true);
root->set_as_audio_listener_2d(true);
current_scene = nullptr;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 8e7182df46..908950a714 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -184,24 +184,6 @@ public:
/////////////////////////////////////
-void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
- Transform3D object_transform = p_object->get_global_transform();
- Transform3D camera_transform = p_camera->get_global_transform();
- ObjectID id = p_object->get_instance_id();
-
- //avoid sending the fake event unnecessarily if nothing really changed in the context
- if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
- Ref<InputEventMouseMotion> mm = p_input_event;
- if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
- return; //discarded
- }
- }
- p_object->_input_event(camera_3d, p_input_event, p_pos, p_normal, p_shape);
- physics_last_object_transform = object_transform;
- physics_last_camera_transform = camera_transform;
- physics_last_id = id;
-}
-
void Viewport::_sub_window_update_order() {
for (int i = 0; i < gui.sub_windows.size(); i++) {
RS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i);
@@ -388,27 +370,6 @@ void Viewport::_sub_window_remove(Window *p_window) {
RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID());
}
-void Viewport::_own_world_3d_changed() {
- ERR_FAIL_COND(world_3d.is_null());
- ERR_FAIL_COND(own_world_3d.is_null());
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- own_world_3d = world_3d->duplicate();
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
void Viewport::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
@@ -422,19 +383,16 @@ void Viewport::_notification(int p_what) {
}
current_canvas = find_world_2d()->get_canvas();
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
-
- _update_listener();
_update_listener_2d();
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ _update_listener_3d();
add_to_group("_viewports");
if (get_tree()->is_debugging_collisions_hint()) {
- //2D
PhysicsServer2D::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_2d_debug = RenderingServer::get_singleton()->canvas_item_create();
RenderingServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, find_world_2d()->get_canvas());
- //3D
PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world_3d()->get_space(), get_tree()->get_collision_debug_contact_count());
contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create();
RenderingServer::get_singleton()->multimesh_allocate_data(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true);
@@ -444,15 +402,13 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh);
RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world_3d()->get_scenario());
//RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
- set_physics_process_internal(true);
}
} break;
case NOTIFICATION_READY: {
-#ifndef _3D_DISABLED
- if (listeners.size() && !listener) {
+ if (listener_3d_set.size() && !listener_3d) {
Listener3D *first = nullptr;
- for (Set<Listener3D *>::Element *E = listeners.front(); E; E = E->next()) {
+ for (Set<Listener3D *>::Element *E = listener_3d_set.front(); E; E = E->next()) {
if (first == nullptr || first->is_greater_than(E->get())) {
first = E->get();
}
@@ -463,10 +419,10 @@ void Viewport::_notification(int p_what) {
}
}
- if (cameras.size() && !camera_3d) {
+ if (camera_3d_set.size() && !camera_3d) {
//there are cameras but no current camera, pick first in tree and make it current
Camera3D *first = nullptr;
- for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
+ for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) {
if (first == nullptr || first->is_greater_than(E->get())) {
first = E->get();
}
@@ -476,7 +432,6 @@ void Viewport::_notification(int p_what) {
first->make_current();
}
}
-#endif
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -515,7 +470,6 @@ void Viewport::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(contact_2d_debug, Rect2(points[i] - Vector2(2, 2), Vector2(5, 5)), ccol);
}
}
-
if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) {
Vector<Vector3> points = PhysicsServer3D::get_singleton()->space_get_contacts(find_world_3d()->get_space());
int point_count = PhysicsServer3D::get_singleton()->space_get_contact_count(find_world_3d()->get_space());
@@ -560,11 +514,9 @@ void Viewport::_process_picking() {
_drop_physics_mouseover(true);
-#ifndef _3D_DISABLED
Vector2 last_pos(1e20, 1e20);
CollisionObject3D *last_object = nullptr;
ObjectID last_id;
-#endif
PhysicsDirectSpaceState3D::RayResult result;
PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
@@ -725,13 +677,12 @@ void Viewport::_process_picking() {
}
}
-#ifndef _3D_DISABLED
bool captured = false;
if (physics_object_capture.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_capture));
if (co && camera_3d) {
- _collision_object_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0);
+ _collision_object_3d_input_event(co, camera_3d, ev, Vector3(), Vector3(), 0);
captured = true;
if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
physics_object_capture = ObjectID();
@@ -748,7 +699,7 @@ void Viewport::_process_picking() {
if (last_id.is_valid()) {
if (ObjectDB::get_instance(last_id) && last_object) {
//good, exists
- _collision_object_input_event(last_object, camera_3d, ev, result.position, result.normal, result.shape);
+ _collision_object_3d_input_event(last_object, camera_3d, ev, result.position, result.normal, result.shape);
if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
physics_object_capture = last_id;
}
@@ -765,8 +716,8 @@ void Viewport::_process_picking() {
ObjectID new_collider;
if (col) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(result.collider);
- if (co) {
- _collision_object_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
+ if (co && co->can_process()) {
+ _collision_object_3d_input_event(co, camera_3d, ev, result.position, result.normal, result.shape);
last_object = co;
last_id = result.collider_id;
new_collider = last_id;
@@ -798,7 +749,6 @@ void Viewport::_process_picking() {
last_pos = pos;
}
}
-#endif
}
}
@@ -865,31 +815,15 @@ Rect2 Viewport::get_visible_rect() const {
return r;
}
-void Viewport::_update_listener() {
-}
-
void Viewport::_update_listener_2d() {
/*
- if (is_inside_tree() && audio_listener && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
+ if (is_inside_tree() && audio_listener_3d && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, find_world_2d()->get_sound_space());
else
SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, RID());
*/
}
-void Viewport::set_as_audio_listener(bool p_enable) {
- if (p_enable == audio_listener) {
- return;
- }
-
- audio_listener = p_enable;
- _update_listener();
-}
-
-bool Viewport::is_audio_listener() const {
- return audio_listener;
-}
-
void Viewport::set_as_audio_listener_2d(bool p_enable) {
if (p_enable == audio_listener_2d) {
return;
@@ -904,15 +838,6 @@ bool Viewport::is_audio_listener_2d() const {
return audio_listener_2d;
}
-void Viewport::set_disable_3d(bool p_disable) {
- disable_3d = p_disable;
- RenderingServer::get_singleton()->viewport_set_disable_3d(viewport, disable_3d);
-}
-
-bool Viewport::is_3d_disabled() const {
- return disable_3d;
-}
-
void Viewport::enable_canvas_transform_override(bool p_enable) {
if (override_canvas_transform == p_enable) {
return;
@@ -973,131 +898,10 @@ Transform2D Viewport::get_global_canvas_transform() const {
return global_canvas_transform;
}
-void Viewport::_listener_transform_changed_notify() {
-}
-
-void Viewport::_listener_set(Listener3D *p_listener) {
-#ifndef _3D_DISABLED
-
- if (listener == p_listener) {
- return;
- }
-
- listener = p_listener;
-
- _update_listener();
- _listener_transform_changed_notify();
-#endif
-}
-
-bool Viewport::_listener_add(Listener3D *p_listener) {
- listeners.insert(p_listener);
- return listeners.size() == 1;
-}
-
-void Viewport::_listener_remove(Listener3D *p_listener) {
- listeners.erase(p_listener);
- if (listener == p_listener) {
- listener = nullptr;
- }
-}
-
-#ifndef _3D_DISABLED
-void Viewport::_listener_make_next_current(Listener3D *p_exclude) {
- if (listeners.size() > 0) {
- for (Set<Listener3D *>::Element *E = listeners.front(); E; E = E->next()) {
- if (p_exclude == E->get()) {
- continue;
- }
- if (!E->get()->is_inside_tree()) {
- continue;
- }
- if (listener != nullptr) {
- return;
- }
-
- E->get()->make_current();
- }
- } else {
- // Attempt to reset listener to the camera position
- if (camera_3d != nullptr) {
- _update_listener();
- _camera_3d_transform_changed_notify();
- }
- }
-}
-#endif
-
-void Viewport::_camera_3d_transform_changed_notify() {
-#ifndef _3D_DISABLED
-#endif
-}
-
-void Viewport::_camera_3d_set(Camera3D *p_camera) {
-#ifndef _3D_DISABLED
-
- if (camera_3d == p_camera) {
- return;
- }
-
- if (camera_3d) {
- camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- }
-
- camera_3d = p_camera;
-
- if (!camera_override) {
- if (camera_3d) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
- } else {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
- }
- }
-
- if (camera_3d) {
- camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
- }
-
- _update_listener();
- _camera_3d_transform_changed_notify();
-#endif
-}
-
void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
camera_2d = p_camera_2d;
}
-bool Viewport::_camera_3d_add(Camera3D *p_camera) {
- cameras.insert(p_camera);
- return cameras.size() == 1;
-}
-
-void Viewport::_camera_3d_remove(Camera3D *p_camera) {
- cameras.erase(p_camera);
- if (camera_3d == p_camera) {
- camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
- camera_3d = nullptr;
- }
-}
-
-#ifndef _3D_DISABLED
-void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
- for (Set<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
- if (p_exclude == E->get()) {
- continue;
- }
- if (!E->get()->is_inside_tree()) {
- continue;
- }
- if (camera_3d != nullptr) {
- return;
- }
-
- E->get()->make_current();
- }
-}
-#endif
-
void Viewport::_canvas_layer_add(CanvasLayer *p_canvas_layer) {
canvas_layers.insert(p_canvas_layer);
}
@@ -1121,7 +925,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
}
if (parent && parent->find_world_2d() == p_world_2d) {
- WARN_PRINT("Unable to use parent world_3d as world_2d");
+ WARN_PRINT("Unable to use parent world_2d as world_2d");
return;
}
@@ -1154,33 +958,6 @@ Ref<World2D> Viewport::find_world_2d() const {
}
}
-void Viewport::_propagate_enter_world(Node *p_node) {
- if (p_node != this) {
- if (!p_node->is_inside_tree()) { //may not have entered scene yet
- return;
- }
-
-#ifndef _3D_DISABLED
- if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
- p_node->notification(Node3D::NOTIFICATION_ENTER_WORLD);
- } else {
-#endif
- Viewport *v = Object::cast_to<Viewport>(p_node);
- if (v) {
- if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
- return;
- }
- }
-#ifndef _3D_DISABLED
- }
-#endif
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_enter_world(p_node->get_child(i));
- }
-}
-
void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
p_node->notification(p_what);
for (int i = 0; i < p_node->get_child_count(); i++) {
@@ -1192,174 +969,14 @@ void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
}
}
-void Viewport::_propagate_exit_world(Node *p_node) {
- if (p_node != this) {
- if (!p_node->is_inside_tree()) { //may have exited scene already
- return;
- }
-
-#ifndef _3D_DISABLED
- if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
- p_node->notification(Node3D::NOTIFICATION_EXIT_WORLD);
- } else {
-#endif
- Viewport *v = Object::cast_to<Viewport>(p_node);
- if (v) {
- if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
- return;
- }
- }
-#ifndef _3D_DISABLED
- }
-#endif
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- _propagate_exit_world(p_node->get_child(i));
- }
-}
-
-void Viewport::set_world_3d(const Ref<World3D> &p_world_3d) {
- if (world_3d == p_world_3d) {
- return;
- }
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- if (own_world_3d.is_valid() && world_3d.is_valid()) {
- world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- }
-
- world_3d = p_world_3d;
-
- if (own_world_3d.is_valid()) {
- if (world_3d.is_valid()) {
- own_world_3d = world_3d->duplicate();
- world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- } else {
- own_world_3d = Ref<World3D>(memnew(World3D));
- }
- }
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
-Ref<World3D> Viewport::get_world_3d() const {
- return world_3d;
-}
-
Ref<World2D> Viewport::get_world_2d() const {
return world_2d;
}
-Ref<World3D> Viewport::find_world_3d() const {
- if (own_world_3d.is_valid()) {
- return own_world_3d;
- } else if (world_3d.is_valid()) {
- return world_3d;
- } else if (parent) {
- return parent->find_world_3d();
- } else {
- return Ref<World3D>();
- }
-}
-
-Listener3D *Viewport::get_listener() const {
- return listener;
-}
-
-Camera3D *Viewport::get_camera_3d() const {
- return camera_3d;
-}
-
Camera2D *Viewport::get_camera_2d() const {
return camera_2d;
}
-void Viewport::enable_camera_override(bool p_enable) {
-#ifndef _3D_DISABLED
- if (p_enable == camera_override) {
- return;
- }
-
- if (p_enable) {
- camera_override.rid = RenderingServer::get_singleton()->camera_create();
- } else {
- RenderingServer::get_singleton()->free(camera_override.rid);
- camera_override.rid = RID();
- }
-
- if (p_enable) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
- } else if (camera_3d) {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
- } else {
- RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
- }
-#endif
-}
-
-bool Viewport::is_camera_override_enabled() const {
- return camera_override;
-}
-
-void Viewport::set_camera_override_transform(const Transform3D &p_transform) {
- if (camera_override) {
- camera_override.transform = p_transform;
- RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
- }
-}
-
-Transform3D Viewport::get_camera_override_transform() const {
- if (camera_override) {
- return camera_override.transform;
- }
-
- return Transform3D();
-}
-
-void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
- if (camera_override) {
- if (camera_override.fov == p_fovy_degrees && camera_override.z_near == p_z_near &&
- camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_PERSPECTIVE) {
- return;
- }
-
- camera_override.fov = p_fovy_degrees;
- camera_override.z_near = p_z_near;
- camera_override.z_far = p_z_far;
- camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE;
-
- RenderingServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far);
- }
-}
-
-void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far) {
- if (camera_override) {
- if (camera_override.size == p_size && camera_override.z_near == p_z_near &&
- camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_ORTHOGONAL) {
- return;
- }
-
- camera_override.size = p_size;
- camera_override.z_near = p_z_near;
- camera_override.z_far = p_z_far;
- camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL;
-
- RenderingServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far);
- }
-}
-
Transform2D Viewport::get_final_transform() const {
return stretch_transform * global_canvas_transform;
}
@@ -1384,16 +1001,6 @@ void Viewport::_update_canvas_items(Node *p_node) {
}
}
-void Viewport::set_use_xr(bool p_use_xr) {
- use_xr = p_use_xr;
-
- RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
-}
-
-bool Viewport::is_using_xr() {
- return use_xr;
-}
-
Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
@@ -2605,7 +2212,6 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
_cleanup_mouseover_colliders(true, p_paused_only);
-#ifndef _3D_DISABLED
if (physics_object_over.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
if (co) {
@@ -2616,7 +2222,6 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
}
}
}
-#endif
}
void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
@@ -3099,6 +2704,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(p_event.is_null());
ERR_FAIL_COND(!is_inside_tree());
+ local_input_handled = false;
if (disable_input || !_can_consume_input_events()) {
return;
@@ -3118,8 +2724,8 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
// Unhandled Input
get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
- // Unhandled key Input - used for performance reasons - This is called a lot less then _unhandled_input since it ignores MouseMotion, etc
- if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != nullptr) {
+ // Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc
+ if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr)) {
get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
}
@@ -3137,44 +2743,6 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
}
}
-void Viewport::set_use_own_world_3d(bool p_world_3d) {
- if (p_world_3d == own_world_3d.is_valid()) {
- return;
- }
-
- if (is_inside_tree()) {
- _propagate_exit_world(this);
- }
-
- if (!p_world_3d) {
- own_world_3d = Ref<World3D>();
- if (world_3d.is_valid()) {
- world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- }
- } else {
- if (world_3d.is_valid()) {
- own_world_3d = world_3d->duplicate();
- world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
- } else {
- own_world_3d = Ref<World3D>(memnew(World3D));
- }
- }
-
- if (is_inside_tree()) {
- _propagate_enter_world(this);
- }
-
- if (is_inside_tree()) {
- RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
- }
-
- _update_listener();
-}
-
-bool Viewport::is_using_own_world_3d() const {
- return own_world_3d.is_valid();
-}
-
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
if (physics_object_picking) {
@@ -3275,6 +2843,7 @@ void Viewport::set_lod_threshold(float p_pixels) {
lod_threshold = p_pixels;
RS::get_singleton()->viewport_set_lod_threshold(viewport, lod_threshold);
}
+
float Viewport::get_lod_threshold() const {
return lod_threshold;
}
@@ -3487,6 +3056,7 @@ void Viewport::set_sdf_oversize(SDFOversize p_sdf_oversize) {
sdf_oversize = p_sdf_oversize;
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
}
+
Viewport::SDFOversize Viewport::get_sdf_oversize() const {
return sdf_oversize;
}
@@ -3496,17 +3066,413 @@ void Viewport::set_sdf_scale(SDFScale p_sdf_scale) {
sdf_scale = p_sdf_scale;
RS::get_singleton()->viewport_set_sdf_oversize_and_scale(viewport, RS::ViewportSDFOversize(sdf_oversize), RS::ViewportSDFScale(sdf_scale));
}
+
Viewport::SDFScale Viewport::get_sdf_scale() const {
return sdf_scale;
}
+Listener3D *Viewport::get_listener_3d() const {
+ return listener_3d;
+}
+
+void Viewport::set_as_audio_listener_3d(bool p_enable) {
+ if (p_enable == audio_listener_3d) {
+ return;
+ }
+
+ audio_listener_3d = p_enable;
+ _update_listener_3d();
+}
+
+bool Viewport::is_audio_listener_3d() const {
+ return audio_listener_3d;
+}
+
+void Viewport::_update_listener_3d() {
+}
+
+void Viewport::_listener_transform_3d_changed_notify() {
+}
+
+void Viewport::_listener_3d_set(Listener3D *p_listener) {
+ if (listener_3d == p_listener) {
+ return;
+ }
+
+ listener_3d = p_listener;
+
+ _update_listener_3d();
+ _listener_transform_3d_changed_notify();
+}
+
+bool Viewport::_listener_3d_add(Listener3D *p_listener) {
+ listener_3d_set.insert(p_listener);
+ return listener_3d_set.size() == 1;
+}
+
+void Viewport::_listener_3d_remove(Listener3D *p_listener) {
+ listener_3d_set.erase(p_listener);
+ if (listener_3d == p_listener) {
+ listener_3d = nullptr;
+ }
+}
+
+void Viewport::_listener_3d_make_next_current(Listener3D *p_exclude) {
+ if (listener_3d_set.size() > 0) {
+ for (Set<Listener3D *>::Element *E = listener_3d_set.front(); E; E = E->next()) {
+ if (p_exclude == E->get()) {
+ continue;
+ }
+ if (!E->get()->is_inside_tree()) {
+ continue;
+ }
+ if (listener_3d != nullptr) {
+ return;
+ }
+
+ E->get()->make_current();
+ }
+ } else {
+ // Attempt to reset listener to the camera position
+ if (camera_3d != nullptr) {
+ _update_listener_3d();
+ _camera_3d_transform_changed_notify();
+ }
+ }
+}
+
+void Viewport::_collision_object_3d_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
+ Transform3D object_transform = p_object->get_global_transform();
+ Transform3D camera_transform = p_camera->get_global_transform();
+ ObjectID id = p_object->get_instance_id();
+
+ //avoid sending the fake event unnecessarily if nothing really changed in the context
+ if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
+ Ref<InputEventMouseMotion> mm = p_input_event;
+ if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
+ return; //discarded
+ }
+ }
+ p_object->_input_event(camera_3d, p_input_event, p_pos, p_normal, p_shape);
+ physics_last_object_transform = object_transform;
+ physics_last_camera_transform = camera_transform;
+ physics_last_id = id;
+}
+
+Camera3D *Viewport::get_camera_3d() const {
+ return camera_3d;
+}
+
+void Viewport::_camera_3d_transform_changed_notify() {
+}
+
+void Viewport::_camera_3d_set(Camera3D *p_camera) {
+ if (camera_3d == p_camera) {
+ return;
+ }
+
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ }
+
+ camera_3d = p_camera;
+
+ if (!camera_3d_override) {
+ if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
+ } else {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
+ }
+ }
+
+ if (camera_3d) {
+ camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
+ }
+
+ _update_listener_3d();
+ _camera_3d_transform_changed_notify();
+}
+
+bool Viewport::_camera_3d_add(Camera3D *p_camera) {
+ camera_3d_set.insert(p_camera);
+ return camera_3d_set.size() == 1;
+}
+
+void Viewport::_camera_3d_remove(Camera3D *p_camera) {
+ camera_3d_set.erase(p_camera);
+ if (camera_3d == p_camera) {
+ camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
+ camera_3d = nullptr;
+ }
+}
+
+void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
+ for (Set<Camera3D *>::Element *E = camera_3d_set.front(); E; E = E->next()) {
+ if (p_exclude == E->get()) {
+ continue;
+ }
+ if (!E->get()->is_inside_tree()) {
+ continue;
+ }
+ if (camera_3d != nullptr) {
+ return;
+ }
+
+ E->get()->make_current();
+ }
+}
+
+void Viewport::enable_camera_3d_override(bool p_enable) {
+ if (p_enable == camera_3d_override) {
+ return;
+ }
+
+ if (p_enable) {
+ camera_3d_override.rid = RenderingServer::get_singleton()->camera_create();
+ } else {
+ RenderingServer::get_singleton()->free(camera_3d_override.rid);
+ camera_3d_override.rid = RID();
+ }
+
+ if (p_enable) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d_override.rid);
+ } else if (camera_3d) {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
+ } else {
+ RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
+ }
+}
+
+void Viewport::set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far) {
+ if (camera_3d_override) {
+ if (camera_3d_override.fov == p_fovy_degrees && camera_3d_override.z_near == p_z_near &&
+ camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_PERSPECTIVE) {
+ return;
+ }
+
+ camera_3d_override.fov = p_fovy_degrees;
+ camera_3d_override.z_near = p_z_near;
+ camera_3d_override.z_far = p_z_far;
+ camera_3d_override.projection = Camera3DOverrideData::PROJECTION_PERSPECTIVE;
+
+ RenderingServer::get_singleton()->camera_set_perspective(camera_3d_override.rid, camera_3d_override.fov, camera_3d_override.z_near, camera_3d_override.z_far);
+ }
+}
+
+void Viewport::set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far) {
+ if (camera_3d_override) {
+ if (camera_3d_override.size == p_size && camera_3d_override.z_near == p_z_near &&
+ camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
+ return;
+ }
+
+ camera_3d_override.size = p_size;
+ camera_3d_override.z_near = p_z_near;
+ camera_3d_override.z_far = p_z_far;
+ camera_3d_override.projection = Camera3DOverrideData::PROJECTION_ORTHOGONAL;
+
+ RenderingServer::get_singleton()->camera_set_orthogonal(camera_3d_override.rid, camera_3d_override.size, camera_3d_override.z_near, camera_3d_override.z_far);
+ }
+}
+
+void Viewport::set_disable_3d(bool p_disable) {
+ disable_3d = p_disable;
+ RenderingServer::get_singleton()->viewport_set_disable_3d(viewport, disable_3d);
+}
+
+bool Viewport::is_3d_disabled() const {
+ return disable_3d;
+}
+
+bool Viewport::is_camera_3d_override_enabled() const {
+ return camera_3d_override;
+}
+
+void Viewport::set_camera_3d_override_transform(const Transform3D &p_transform) {
+ if (camera_3d_override) {
+ camera_3d_override.transform = p_transform;
+ RenderingServer::get_singleton()->camera_set_transform(camera_3d_override.rid, p_transform);
+ }
+}
+
+Transform3D Viewport::get_camera_3d_override_transform() const {
+ if (camera_3d_override) {
+ return camera_3d_override.transform;
+ }
+
+ return Transform3D();
+}
+
+Ref<World3D> Viewport::get_world_3d() const {
+ return world_3d;
+}
+
+Ref<World3D> Viewport::find_world_3d() const {
+ if (own_world_3d.is_valid()) {
+ return own_world_3d;
+ } else if (world_3d.is_valid()) {
+ return world_3d;
+ } else if (parent) {
+ return parent->find_world_3d();
+ } else {
+ return Ref<World3D>();
+ }
+}
+
+void Viewport::set_world_3d(const Ref<World3D> &p_world_3d) {
+ if (world_3d == p_world_3d) {
+ return;
+ }
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ if (own_world_3d.is_valid() && world_3d.is_valid()) {
+ world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ }
+
+ world_3d = p_world_3d;
+
+ if (own_world_3d.is_valid()) {
+ if (world_3d.is_valid()) {
+ own_world_3d = world_3d->duplicate();
+ world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ } else {
+ own_world_3d = Ref<World3D>(memnew(World3D));
+ }
+ }
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+void Viewport::_own_world_3d_changed() {
+ ERR_FAIL_COND(world_3d.is_null());
+ ERR_FAIL_COND(own_world_3d.is_null());
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ own_world_3d = world_3d->duplicate();
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+void Viewport::set_use_own_world_3d(bool p_world_3d) {
+ if (p_world_3d == own_world_3d.is_valid()) {
+ return;
+ }
+
+ if (is_inside_tree()) {
+ _propagate_exit_world_3d(this);
+ }
+
+ if (!p_world_3d) {
+ own_world_3d = Ref<World3D>();
+ if (world_3d.is_valid()) {
+ world_3d->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ }
+ } else {
+ if (world_3d.is_valid()) {
+ own_world_3d = world_3d->duplicate();
+ world_3d->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Viewport::_own_world_3d_changed));
+ } else {
+ own_world_3d = Ref<World3D>(memnew(World3D));
+ }
+ }
+
+ if (is_inside_tree()) {
+ _propagate_enter_world_3d(this);
+ }
+
+ if (is_inside_tree()) {
+ RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world_3d()->get_scenario());
+ }
+
+ _update_listener_3d();
+}
+
+bool Viewport::is_using_own_world_3d() const {
+ return own_world_3d.is_valid();
+}
+
+void Viewport::_propagate_enter_world_3d(Node *p_node) {
+ if (p_node != this) {
+ if (!p_node->is_inside_tree()) { //may not have entered scene yet
+ return;
+ }
+
+ if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
+ p_node->notification(Node3D::NOTIFICATION_ENTER_WORLD);
+ } else {
+ Viewport *v = Object::cast_to<Viewport>(p_node);
+ if (v) {
+ if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
+ return;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _propagate_enter_world_3d(p_node->get_child(i));
+ }
+}
+
+void Viewport::_propagate_exit_world_3d(Node *p_node) {
+ if (p_node != this) {
+ if (!p_node->is_inside_tree()) { //may have exited scene already
+ return;
+ }
+
+ if (Object::cast_to<Node3D>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
+ p_node->notification(Node3D::NOTIFICATION_EXIT_WORLD);
+ } else {
+ Viewport *v = Object::cast_to<Viewport>(p_node);
+ if (v) {
+ if (v->world_3d.is_valid() || v->own_world_3d.is_valid()) {
+ return;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _propagate_exit_world_3d(p_node->get_child(i));
+ }
+}
+
+void Viewport::set_use_xr(bool p_use_xr) {
+ use_xr = p_use_xr;
+
+ RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
+}
+
+bool Viewport::is_using_xr() {
+ return use_xr;
+}
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d);
- ClassDB::bind_method(D_METHOD("set_world_3d", "world_3d"), &Viewport::set_world_3d);
- ClassDB::bind_method(D_METHOD("get_world_3d"), &Viewport::get_world_3d);
- ClassDB::bind_method(D_METHOD("find_world_3d"), &Viewport::find_world_3d);
ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &Viewport::set_canvas_transform);
ClassDB::bind_method(D_METHOD("get_canvas_transform"), &Viewport::get_canvas_transform);
@@ -3536,9 +3502,6 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_render_info", "type", "info"), &Viewport::get_render_info);
- ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
- ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
-
ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture);
ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
@@ -3549,21 +3512,10 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d);
- ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d);
-
- ClassDB::bind_method(D_METHOD("get_camera_3d"), &Viewport::get_camera_3d);
ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
-
- ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener);
- ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener);
-
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
- ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
- ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
-
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
@@ -3621,7 +3573,26 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("_process_picking"), &Viewport::_process_picking);
+ ClassDB::bind_method(D_METHOD("set_world_3d", "world_3d"), &Viewport::set_world_3d);
+ ClassDB::bind_method(D_METHOD("get_world_3d"), &Viewport::get_world_3d);
+ ClassDB::bind_method(D_METHOD("find_world_3d"), &Viewport::find_world_3d);
+
+ ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d);
+ ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d);
+
+ ClassDB::bind_method(D_METHOD("get_camera_3d"), &Viewport::get_camera_3d);
+ ClassDB::bind_method(D_METHOD("set_as_audio_listener_3d", "enable"), &Viewport::set_as_audio_listener_3d);
+ ClassDB::bind_method(D_METHOD("is_audio_listener_3d"), &Viewport::is_audio_listener_3d);
+
+ ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
+ ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
+
+ ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
+ ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", PROPERTY_USAGE_NONE), "set_world_2d", "get_world_2d");
@@ -3630,7 +3601,6 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_vertices_to_pixel"), "set_snap_2d_vertices_to_pixel", "is_snap_2d_vertices_to_pixel_enabled");
ADD_GROUP("Rendering", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled (Fastest),2x (Fast),4x (Average),8x (Slow),16x (Slower)"), "set_msaa", "get_msaa");
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_space_aa", PROPERTY_HINT_ENUM, "Disabled (Fastest),FXAA (Fast)"), "set_screen_space_aa", "get_screen_space_aa");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_debanding"), "set_use_debanding", "is_using_debanding");
@@ -3642,7 +3612,6 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener", "is_audio_listener");
ADD_GROUP("Physics", "physics_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
ADD_GROUP("GUI", "gui_");
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index b5c49a8a97..7a25f5aa00 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -194,39 +194,13 @@ private:
Viewport *parent = nullptr;
- Listener3D *listener = nullptr;
- Set<Listener3D *> listeners;
-
- struct CameraOverrideData {
- Transform3D transform;
- enum Projection {
- PROJECTION_PERSPECTIVE,
- PROJECTION_ORTHOGONAL
- };
- Projection projection = Projection::PROJECTION_PERSPECTIVE;
- float fov = 0.0;
- float size = 0.0;
- float z_near = 0.0;
- float z_far = 0.0;
- RID rid;
-
- operator bool() const {
- return rid != RID();
- }
- } camera_override;
-
- Camera3D *camera_3d = nullptr;
Camera2D *camera_2d = nullptr;
- Set<Camera3D *> cameras;
Set<CanvasLayer *> canvas_layers;
RID viewport;
RID current_canvas;
RID subwindow_canvas;
- bool audio_listener = false;
- RID internal_listener;
-
bool audio_listener_2d = false;
RID internal_listener_2d;
@@ -240,7 +214,6 @@ private:
Size2i size = Size2i(512, 512);
Size2i size_2d_override;
bool size_allocated = false;
- bool use_xr = false;
RID contact_2d_debug;
RID contact_3d_debug_multimesh;
@@ -274,8 +247,6 @@ private:
} physics_last_mouse_state;
- void _collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
-
bool handle_input_locally = true;
bool local_input_handled = false;
@@ -287,8 +258,6 @@ private:
void _cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference = 0);
Ref<World2D> world_2d;
- Ref<World3D> world_3d;
- Ref<World3D> own_world_3d;
Rect2i to_screen_rect;
StringName input_group;
@@ -296,13 +265,10 @@ private:
StringName unhandled_input_group;
StringName unhandled_key_input_group;
- void _update_listener();
void _update_listener_2d();
bool disable_3d = false;
- void _propagate_enter_world(Node *p_node);
- void _propagate_exit_world(Node *p_node);
void _propagate_viewport_notification(Node *p_node, int p_what);
void _update_global_transform();
@@ -375,7 +341,7 @@ private:
Variant drag_data;
ObjectID drag_preview_id;
Ref<SceneTreeTimer> tooltip_timer;
- float tooltip_delay = 0.0;
+ double tooltip_delay = 0.0;
Transform2D focus_inv_xform;
bool roots_order_dirty = false;
List<Control *> roots;
@@ -443,20 +409,6 @@ private:
bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check);
- friend class Listener3D;
- void _listener_transform_changed_notify();
- void _listener_set(Listener3D *p_listener);
- bool _listener_add(Listener3D *p_listener); //true if first
- void _listener_remove(Listener3D *p_listener);
- void _listener_make_next_current(Listener3D *p_exclude);
-
- friend class Camera3D;
- void _camera_3d_transform_changed_notify();
- void _camera_3d_set(Camera3D *p_camera);
- bool _camera_3d_add(Camera3D *p_camera); //true if first
- void _camera_3d_remove(Camera3D *p_camera);
- void _camera_3d_make_next_current(Camera3D *p_exclude);
-
friend class Camera2D;
void _camera_2d_set(Camera2D *p_camera_2d);
@@ -471,8 +423,6 @@ private:
void _gui_set_root_order_dirty();
- void _own_world_3d_changed();
-
friend class Window;
void _sub_window_update_order();
@@ -500,38 +450,16 @@ protected:
public:
uint64_t get_processed_events_count() const { return event_count; }
- Listener3D *get_listener() const;
- Camera3D *get_camera_3d() const;
Camera2D *get_camera_2d() const;
-
- void enable_camera_override(bool p_enable);
- bool is_camera_override_enabled() const;
-
- void set_camera_override_transform(const Transform3D &p_transform);
- Transform3D get_camera_override_transform() const;
-
- void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
- void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
-
- void set_as_audio_listener(bool p_enable);
- bool is_audio_listener() const;
-
void set_as_audio_listener_2d(bool p_enable);
bool is_audio_listener_2d() const;
- void set_disable_3d(bool p_disable);
- bool is_3d_disabled() const;
-
void update_canvas_items();
Rect2 get_visible_rect() const;
RID get_viewport_rid() const;
- void set_world_3d(const Ref<World3D> &p_world_3d);
void set_world_2d(const Ref<World2D> &p_world_2d);
- Ref<World3D> get_world_3d() const;
- Ref<World3D> find_world_3d() const;
-
Ref<World2D> get_world_2d() const;
Ref<World2D> find_world_2d() const;
@@ -552,9 +480,6 @@ public:
void set_transparent_background(bool p_enable);
bool has_transparent_background() const;
- void set_use_xr(bool p_use_xr);
- bool is_using_xr();
-
Ref<ViewportTexture> get_texture() const;
void set_shadow_atlas_size(int p_size);
@@ -584,9 +509,6 @@ public:
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
Vector2 get_camera_rect_size() const;
- void set_use_own_world_3d(bool p_world_3d);
- bool is_using_own_world_3d() const;
-
void input_text(const String &p_text);
void input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
@@ -654,6 +576,78 @@ public:
void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
+ bool use_xr = false;
+ friend class Listener3D;
+ Listener3D *listener_3d = nullptr;
+ Set<Listener3D *> listener_3d_set;
+ bool audio_listener_3d = false;
+ RID internal_listener_3d;
+ Listener3D *get_listener_3d() const;
+ void set_as_audio_listener_3d(bool p_enable);
+ bool is_audio_listener_3d() const;
+ void _update_listener_3d();
+ void _listener_transform_3d_changed_notify();
+ void _listener_3d_set(Listener3D *p_listener);
+ bool _listener_3d_add(Listener3D *p_listener); //true if first
+ void _listener_3d_remove(Listener3D *p_listener);
+ void _listener_3d_make_next_current(Listener3D *p_exclude);
+
+ void _collision_object_3d_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape);
+
+ struct Camera3DOverrideData {
+ Transform3D transform;
+ enum Projection {
+ PROJECTION_PERSPECTIVE,
+ PROJECTION_ORTHOGONAL
+ };
+ Projection projection = Projection::PROJECTION_PERSPECTIVE;
+ real_t fov = 0.0;
+ real_t size = 0.0;
+ real_t z_near = 0.0;
+ real_t z_far = 0.0;
+ RID rid;
+
+ operator bool() const {
+ return rid != RID();
+ }
+ } camera_3d_override;
+
+ friend class Camera3D;
+ Camera3D *camera_3d = nullptr;
+ Set<Camera3D *> camera_3d_set;
+ Camera3D *get_camera_3d() const;
+ void _camera_3d_transform_changed_notify();
+ void _camera_3d_set(Camera3D *p_camera);
+ bool _camera_3d_add(Camera3D *p_camera); //true if first
+ void _camera_3d_remove(Camera3D *p_camera);
+ void _camera_3d_make_next_current(Camera3D *p_exclude);
+
+ void enable_camera_3d_override(bool p_enable);
+ bool is_camera_3d_override_enabled() const;
+
+ void set_camera_3d_override_transform(const Transform3D &p_transform);
+ Transform3D get_camera_3d_override_transform() const;
+
+ void set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
+ void set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
+
+ void set_disable_3d(bool p_disable);
+ bool is_3d_disabled() const;
+
+ Ref<World3D> world_3d;
+ Ref<World3D> own_world_3d;
+ void set_world_3d(const Ref<World3D> &p_world_3d);
+ Ref<World3D> get_world_3d() const;
+ Ref<World3D> find_world_3d() const;
+ void _own_world_3d_changed();
+ void set_use_own_world_3d(bool p_world_3d);
+ bool is_using_own_world_3d() const;
+ void _propagate_enter_world_3d(Node *p_node);
+ void _propagate_exit_world_3d(Node *p_node);
+
+ void set_use_xr(bool p_use_xr);
+ bool is_using_xr();
+
Viewport();
~Viewport();
};
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 640ec50eb9..e6a74e7685 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -77,17 +77,17 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
} else if (what == "keys" || what == "key_values") {
if (track_get_type(track) == TYPE_TRANSFORM3D) {
TransformTrack *tt = static_cast<TransformTrack *>(tracks[track]);
- Vector<float> values = p_value;
+ Vector<real_t> values = p_value;
int vcount = values.size();
- ERR_FAIL_COND_V(vcount % 12, false); // should be multiple of 11
+ ERR_FAIL_COND_V(vcount % 12, false); // should be multiple of 12
- const float *r = values.ptr();
+ const real_t *r = values.ptr();
tt->transforms.resize(vcount / 12);
for (int i = 0; i < (vcount / 12); i++) {
TKey<TransformKey> &tk = tt->transforms.write[i];
- const float *ofs = &r[i * 12];
+ const real_t *ofs = &r[i * 12];
tk.time = ofs[0];
tk.transition = ofs[1];
@@ -125,7 +125,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
vt->update_mode = UpdateMode(um);
}
- Vector<float> times = d["times"];
+ Vector<real_t> times = d["times"];
Array values = d["values"];
ERR_FAIL_COND_V(times.size() != values.size(), false);
@@ -133,7 +133,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (times.size()) {
int valcount = times.size();
- const float *rt = times.ptr();
+ const real_t *rt = times.ptr();
vt->values.resize(valcount);
@@ -143,10 +143,10 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
}
if (d.has("transitions")) {
- Vector<float> transitions = d["transitions"];
+ Vector<real_t> transitions = d["transitions"];
ERR_FAIL_COND_V(transitions.size() != valcount, false);
- const float *rtr = transitions.ptr();
+ const real_t *rtr = transitions.ptr();
for (int i = 0; i < valcount; i++) {
vt->values.write[i].transition = rtr[i];
@@ -165,7 +165,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("times"), false);
ERR_FAIL_COND_V(!d.has("values"), false);
- Vector<float> times = d["times"];
+ Vector<real_t> times = d["times"];
Array values = d["values"];
ERR_FAIL_COND_V(times.size() != values.size(), false);
@@ -173,17 +173,17 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (times.size()) {
int valcount = times.size();
- const float *rt = times.ptr();
+ const real_t *rt = times.ptr();
for (int i = 0; i < valcount; i++) {
track_insert_key(track, rt[i], values[i]);
}
if (d.has("transitions")) {
- Vector<float> transitions = d["transitions"];
+ Vector<real_t> transitions = d["transitions"];
ERR_FAIL_COND_V(transitions.size() != valcount, false);
- const float *rtr = transitions.ptr();
+ const real_t *rtr = transitions.ptr();
for (int i = 0; i < valcount; i++) {
track_set_key_transition(track, i, rtr[i]);
@@ -196,16 +196,16 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("times"), false);
ERR_FAIL_COND_V(!d.has("points"), false);
- Vector<float> times = d["times"];
- PackedFloat32Array values = d["points"];
+ Vector<real_t> times = d["times"];
+ Vector<real_t> values = d["points"];
ERR_FAIL_COND_V(times.size() * 5 != values.size(), false);
if (times.size()) {
int valcount = times.size();
- const float *rt = times.ptr();
- const float *rv = values.ptr();
+ const real_t *rt = times.ptr();
+ const real_t *rv = values.ptr();
bt->values.resize(valcount);
@@ -227,7 +227,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("times"), false);
ERR_FAIL_COND_V(!d.has("clips"), false);
- Vector<float> times = d["times"];
+ Vector<real_t> times = d["times"];
Array clips = d["clips"];
ERR_FAIL_COND_V(clips.size() != times.size(), false);
@@ -235,7 +235,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (times.size()) {
int valcount = times.size();
- const float *rt = times.ptr();
+ const real_t *rt = times.ptr();
ad->values.clear();
@@ -268,7 +268,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
ERR_FAIL_COND_V(!d.has("times"), false);
ERR_FAIL_COND_V(!d.has("clips"), false);
- Vector<float> times = d["times"];
+ Vector<real_t> times = d["times"];
Vector<String> clips = d["clips"];
ERR_FAIL_COND_V(clips.size() != times.size(), false);
@@ -276,7 +276,7 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (times.size()) {
int valcount = times.size();
- const float *rt = times.ptr();
+ const real_t *rt = times.ptr();
const String *rc = clips.ptr();
an->values.resize(valcount);
@@ -352,9 +352,9 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = track_is_enabled(track);
} else if (what == "keys") {
if (track_get_type(track) == TYPE_TRANSFORM3D) {
- Vector<float> keys;
+ Vector<real_t> keys;
int kk = track_get_key_count(track);
- keys.resize(kk * 12);
+ keys.resize(kk * sizeof(Transform3D));
real_t *w = keys.ptrw();
@@ -389,8 +389,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
Dictionary d;
- Vector<float> key_times;
- Vector<float> key_transitions;
+ Vector<real_t> key_times;
+ Vector<real_t> key_transitions;
Array key_values;
int kk = vt->values.size();
@@ -399,8 +399,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
key_transitions.resize(kk);
key_values.resize(kk);
- float *wti = key_times.ptrw();
- float *wtr = key_transitions.ptrw();
+ real_t *wti = key_times.ptrw();
+ real_t *wtr = key_transitions.ptrw();
int idx = 0;
@@ -427,8 +427,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
} else if (track_get_type(track) == TYPE_METHOD) {
Dictionary d;
- Vector<float> key_times;
- Vector<float> key_transitions;
+ Vector<real_t> key_times;
+ Vector<real_t> key_transitions;
Array key_values;
int kk = track_get_key_count(track);
@@ -437,8 +437,8 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
key_transitions.resize(kk);
key_values.resize(kk);
- float *wti = key_times.ptrw();
- float *wtr = key_transitions.ptrw();
+ real_t *wti = key_times.ptrw();
+ real_t *wtr = key_transitions.ptrw();
int idx = 0;
for (int i = 0; i < track_get_key_count(track); i++) {
@@ -463,16 +463,16 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
Dictionary d;
- Vector<float> key_times;
- Vector<float> key_points;
+ Vector<real_t> key_times;
+ Vector<real_t> key_points;
int kk = bt->values.size();
key_times.resize(kk);
key_points.resize(kk * 5);
- float *wti = key_times.ptrw();
- float *wpo = key_points.ptrw();
+ real_t *wti = key_times.ptrw();
+ real_t *wpo = key_points.ptrw();
int idx = 0;
@@ -499,14 +499,14 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
Dictionary d;
- Vector<float> key_times;
+ Vector<real_t> key_times;
Array clips;
int kk = ad->values.size();
key_times.resize(kk);
- float *wti = key_times.ptrw();
+ real_t *wti = key_times.ptrw();
int idx = 0;
@@ -533,7 +533,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
Dictionary d;
- Vector<float> key_times;
+ Vector<real_t> key_times;
Vector<String> clips;
int kk = an->values.size();
@@ -541,7 +541,7 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
key_times.resize(kk);
clips.resize(kk);
- float *wti = key_times.ptrw();
+ real_t *wti = key_times.ptrw();
String *wcl = clips.ptrw();
const TKey<StringName> *vls = an->values.ptr();
@@ -722,7 +722,7 @@ bool Animation::track_get_interpolation_loop_wrap(int p_track) const {
// transform
/*
template<class T>
-int Animation::_insert_pos(float p_time, T& p_keys) {
+int Animation::_insert_pos(double p_time, T& p_keys) {
// simple, linear time inset that should be fast enough in reality.
int idx=p_keys.size();
@@ -745,12 +745,12 @@ int Animation::_insert_pos(float p_time, T& p_keys) {
*/
template <class T, class V>
-int Animation::_insert(float p_time, T &p_keys, const V &p_value) {
+int Animation::_insert(double p_time, T &p_keys, const V &p_value) {
int idx = p_keys.size();
while (true) {
// Condition for replacement.
- if (idx > 0 && Math::is_equal_approx(p_keys[idx - 1].time, p_time)) {
+ if (idx > 0 && Math::is_equal_approx((double)p_keys[idx - 1].time, p_time)) {
float transition = p_keys[idx - 1].transition;
p_keys.write[idx - 1] = p_value;
p_keys.write[idx - 1].transition = transition;
@@ -794,7 +794,7 @@ Error Animation::transform_track_get_key(int p_track, int p_key, Vector3 *r_loc,
return OK;
}
-int Animation::transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quaternion &p_rot, const Vector3 &p_scale) {
+int Animation::transform_track_insert_key(int p_track, double p_time, const Vector3 &p_loc, const Quaternion &p_rot, const Vector3 &p_scale) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, -1);
@@ -812,7 +812,7 @@ int Animation::transform_track_insert_key(int p_track, float p_time, const Vecto
return ret;
}
-void Animation::track_remove_key_at_time(int p_track, float p_time) {
+void Animation::track_remove_key_at_time(int p_track, double p_time) {
int idx = track_find_key(p_track, p_time, true);
ERR_FAIL_COND(idx < 0);
track_remove_key(p_track, idx);
@@ -864,7 +864,7 @@ void Animation::track_remove_key(int p_track, int p_idx) {
emit_changed();
}
-int Animation::track_find_key(int p_track, float p_time, bool p_exact) const {
+int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@@ -946,7 +946,7 @@ int Animation::track_find_key(int p_track, float p_time, bool p_exact) const {
return -1;
}
-void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition) {
+void Animation::track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
@@ -1151,7 +1151,7 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const {
ERR_FAIL_V(Variant());
}
-float Animation::track_get_key_time(int p_track, int p_key_idx) const {
+double Animation::track_get_key_time(int p_track, int p_key_idx) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@@ -1196,7 +1196,7 @@ float Animation::track_get_key_time(int p_track, int p_key_idx) const {
ERR_FAIL_V(-1);
}
-void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) {
+void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
@@ -1260,7 +1260,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, float p_time) {
ERR_FAIL();
}
-float Animation::track_get_key_transition(int p_track, int p_key_idx) const {
+real_t Animation::track_get_key_transition(int p_track, int p_key_idx) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
@@ -1379,7 +1379,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
emit_changed();
}
-void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_transition) {
+void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_transition) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
@@ -1412,7 +1412,7 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, float p_tra
}
template <class K>
-int Animation::_find(const Vector<K> &p_keys, float p_time) const {
+int Animation::_find(const Vector<K> &p_keys, double p_time) const {
int len = p_keys.size();
if (len == 0) {
return -2;
@@ -1433,7 +1433,7 @@ int Animation::_find(const Vector<K> &p_keys, float p_time) const {
while (low <= high) {
middle = (low + high) / 2;
- if (Math::is_equal_approx(p_time, keys[middle].time)) { //match
+ if (Math::is_equal_approx(p_time, (double)keys[middle].time)) { //match
return middle;
} else if (p_time < keys[middle].time) {
high = middle - 1; //search low end of array
@@ -1449,7 +1449,7 @@ int Animation::_find(const Vector<K> &p_keys, float p_time) const {
return middle;
}
-Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const {
+Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, real_t p_c) const {
TransformKey ret;
ret.loc = _interpolate(p_a.loc, p_b.loc, p_c);
ret.rot = _interpolate(p_a.rot, p_b.rot, p_c);
@@ -1458,25 +1458,25 @@ Animation::TransformKey Animation::_interpolate(const Animation::TransformKey &p
return ret;
}
-Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const {
+Vector3 Animation::_interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const {
return p_a.lerp(p_b, p_c);
}
-Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b, float p_c) const {
+Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const {
return p_a.slerp(p_b, p_c);
}
-Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, float p_c) const {
+Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const {
Variant dst;
Variant::interpolate(p_a, p_b, p_c, dst);
return dst;
}
-float Animation::_interpolate(const float &p_a, const float &p_b, float p_c) const {
+real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const {
return p_a * (1.0 - p_c) + p_b * p_c;
}
-Animation::TransformKey Animation::_cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const {
+Animation::TransformKey Animation::_cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, real_t p_c) const {
Animation::TransformKey tk;
tk.loc = p_a.loc.cubic_interpolate(p_b.loc, p_pre_a.loc, p_post_b.loc, p_c);
@@ -1486,15 +1486,15 @@ Animation::TransformKey Animation::_cubic_interpolate(const Animation::Transform
return tk;
}
-Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const {
+Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const {
return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c);
}
-Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, float p_c) const {
+Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const {
return p_a.cubic_slerp(p_b, p_pre_a, p_post_b, p_c);
}
-Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) const {
+Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const {
Variant::Type type_a = p_a.get_type();
Variant::Type type_b = p_b.get_type();
Variant::Type type_pa = p_pre_a.get_type();
@@ -1515,9 +1515,9 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
real_t p2 = p_b;
real_t p3 = p_post_b;
- float t = p_c;
- float t2 = t * t;
- float t3 = t2 * t;
+ real_t t = p_c;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
return 0.5f * ((p1 * 2.0f) +
(-p0 + p2) * t +
@@ -1579,12 +1579,12 @@ Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a
}
}
-float Animation::_cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const {
+real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const {
return _interpolate(p_a, p_b, p_c);
}
template <class T>
-T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const {
+T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const {
int len = _find(p_keys, length) + 1; // try to find last key (there may be more past the end)
if (len <= 0) {
@@ -1608,7 +1608,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
bool result = true;
int next = 0;
- float c = 0.0;
+ real_t c = 0.0;
// prepare for all cases of interpolation
if (loop && p_loop_wrap) {
@@ -1616,8 +1616,8 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
if (idx >= 0) {
if ((idx + 1) < len) {
next = idx + 1;
- float delta = p_keys[next].time - p_keys[idx].time;
- float from = p_time - p_keys[idx].time;
+ real_t delta = p_keys[next].time - p_keys[idx].time;
+ real_t from = p_time - p_keys[idx].time;
if (Math::is_zero_approx(delta)) {
c = 0;
@@ -1627,8 +1627,8 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
} else {
next = 0;
- float delta = (length - p_keys[idx].time) + p_keys[next].time;
- float from = p_time - p_keys[idx].time;
+ real_t delta = (length - p_keys[idx].time) + p_keys[next].time;
+ real_t from = p_time - p_keys[idx].time;
if (Math::is_zero_approx(delta)) {
c = 0;
@@ -1641,12 +1641,12 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
// on loop, behind first key
idx = len - 1;
next = 0;
- float endtime = (length - p_keys[idx].time);
+ real_t endtime = (length - p_keys[idx].time);
if (endtime < 0) { // may be keys past the end
endtime = 0;
}
- float delta = endtime + p_keys[next].time;
- float from = endtime + p_time;
+ real_t delta = endtime + p_keys[next].time;
+ real_t from = endtime + p_time;
if (Math::is_zero_approx(delta)) {
c = 0;
@@ -1660,8 +1660,8 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
if (idx >= 0) {
if ((idx + 1) < len) {
next = idx + 1;
- float delta = p_keys[next].time - p_keys[idx].time;
- float from = p_time - p_keys[idx].time;
+ real_t delta = p_keys[next].time - p_keys[idx].time;
+ real_t from = p_time - p_keys[idx].time;
if (Math::is_zero_approx(delta)) {
c = 0;
@@ -1690,7 +1690,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
return T();
}
- float tr = p_keys[idx].transition;
+ real_t tr = p_keys[idx].transition;
if (tr == 0 || idx == next) {
// don't interpolate if not needed
@@ -1728,7 +1728,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, float p_time, Interpola
// do a barrel roll
}
-Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const {
+Error Animation::transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_TRANSFORM3D, ERR_INVALID_PARAMETER);
@@ -1758,7 +1758,7 @@ Error Animation::transform_track_interpolate(int p_track, float p_time, Vector3
return OK;
}
-Variant Animation::value_track_interpolate(int p_track, float p_time) const {
+Variant Animation::value_track_interpolate(int p_track, double p_time) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_VALUE, Variant());
@@ -1775,7 +1775,7 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const {
return Variant();
}
-void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const {
+void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const {
if (from_time != length && to_time == length) {
to_time = length * 1.001; //include a little more if at the end
}
@@ -1812,15 +1812,15 @@ void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, floa
}
}
-void Animation::value_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const {
+void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_VALUE);
ValueTrack *vt = static_cast<ValueTrack *>(t);
- float from_time = p_time - p_delta;
- float to_time = p_time;
+ double from_time = p_time - p_delta;
+ double to_time = p_time;
if (from_time > to_time) {
SWAP(from_time, to_time);
@@ -1875,7 +1875,7 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const
}
template <class T>
-void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, float from_time, float to_time, List<int> *p_indices) const {
+void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const {
if (from_time != length && to_time == length) {
to_time = length * 1.01; //include a little more if at the end
}
@@ -1908,12 +1908,12 @@ void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, float
}
}
-void Animation::track_get_key_indices_in_range(int p_track, float p_time, float p_delta, List<int> *p_indices) const {
+void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
const Track *t = tracks[p_track];
- float from_time = p_time - p_delta;
- float to_time = p_time;
+ double from_time = p_time - p_delta;
+ double to_time = p_time;
if (from_time > to_time) {
SWAP(from_time, to_time);
@@ -2021,7 +2021,7 @@ void Animation::track_get_key_indices_in_range(int p_track, float p_time, float
}
}
-void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const {
+void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const {
if (from_time != length && to_time == length) {
to_time = length * 1.01; //include a little more if at the end
}
@@ -2054,15 +2054,15 @@ void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, fl
}
}
-void Animation::method_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const {
+void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_METHOD);
MethodTrack *mt = static_cast<MethodTrack *>(t);
- float from_time = p_time - p_delta;
- float to_time = p_time;
+ double from_time = p_time - p_delta;
+ double to_time = p_time;
if (from_time > to_time) {
SWAP(from_time, to_time);
@@ -2128,7 +2128,7 @@ StringName Animation::method_track_get_name(int p_track, int p_key_idx) const {
return pm->methods[p_key_idx].method;
}
-int Animation::bezier_track_insert_key(int p_track, float p_time, float p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle) {
+int Animation::bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_BEZIER, -1);
@@ -2154,7 +2154,7 @@ int Animation::bezier_track_insert_key(int p_track, float p_time, float p_value,
return key;
}
-void Animation::bezier_track_set_key_value(int p_track, int p_index, float p_value) {
+void Animation::bezier_track_set_key_value(int p_track, int p_index, real_t p_value) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_BEZIER);
@@ -2199,7 +2199,7 @@ void Animation::bezier_track_set_key_out_handle(int p_track, int p_index, const
emit_changed();
}
-float Animation::bezier_track_get_key_value(int p_track, int p_index) const {
+real_t Animation::bezier_track_get_key_value(int p_track, int p_index) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_BEZIER, 0);
@@ -2246,7 +2246,7 @@ static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, const Vector2 &start, con
return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
}
-float Animation::bezier_track_interpolate(int p_track, float p_time) const {
+real_t Animation::bezier_track_interpolate(int p_track, double p_time) const {
//this uses a different interpolation scheme
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
Track *track = tracks[p_track];
@@ -2277,14 +2277,14 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const {
return bt->values[bt->values.size() - 1].value.value;
}
- float t = p_time - bt->values[idx].time;
+ double t = p_time - bt->values[idx].time;
int iterations = 10;
- float duration = bt->values[idx + 1].time - bt->values[idx].time; // time duration between our two keyframes
- float low = 0.0; // 0% of the current animation segment
- float high = 1.0; // 100% of the current animation segment
- float middle;
+ real_t duration = bt->values[idx + 1].time - bt->values[idx].time; // time duration between our two keyframes
+ real_t low = 0.0; // 0% of the current animation segment
+ real_t high = 1.0; // 100% of the current animation segment
+ real_t middle;
Vector2 start(0, bt->values[idx].value.value);
Vector2 start_out = start + bt->values[idx].value.out_handle;
@@ -2307,12 +2307,12 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const {
//interpolate the result:
Vector2 low_pos = _bezier_interp(low, start, start_out, end_in, end);
Vector2 high_pos = _bezier_interp(high, start, start_out, end_in, end);
- float c = (t - low_pos.x) / (high_pos.x - low_pos.x);
+ real_t c = (t - low_pos.x) / (high_pos.x - low_pos.x);
return low_pos.lerp(high_pos, c).y;
}
-int Animation::audio_track_insert_key(int p_track, float p_time, const RES &p_stream, float p_start_offset, float p_end_offset) {
+int Animation::audio_track_insert_key(int p_track, double p_time, const RES &p_stream, real_t p_start_offset, real_t p_end_offset) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_AUDIO, -1);
@@ -2352,7 +2352,7 @@ void Animation::audio_track_set_key_stream(int p_track, int p_key, const RES &p_
emit_changed();
}
-void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p_offset) {
+void Animation::audio_track_set_key_start_offset(int p_track, int p_key, real_t p_offset) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_AUDIO);
@@ -2370,7 +2370,7 @@ void Animation::audio_track_set_key_start_offset(int p_track, int p_key, float p
emit_changed();
}
-void Animation::audio_track_set_key_end_offset(int p_track, int p_key, float p_offset) {
+void Animation::audio_track_set_key_end_offset(int p_track, int p_key, real_t p_offset) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
ERR_FAIL_COND(t->type != TYPE_AUDIO);
@@ -2400,7 +2400,7 @@ RES Animation::audio_track_get_key_stream(int p_track, int p_key) const {
return at->values[p_key].value.stream;
}
-float Animation::audio_track_get_key_start_offset(int p_track, int p_key) const {
+real_t Animation::audio_track_get_key_start_offset(int p_track, int p_key) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
const Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_AUDIO, 0);
@@ -2412,7 +2412,7 @@ float Animation::audio_track_get_key_start_offset(int p_track, int p_key) const
return at->values[p_key].value.start_offset;
}
-float Animation::audio_track_get_key_end_offset(int p_track, int p_key) const {
+real_t Animation::audio_track_get_key_end_offset(int p_track, int p_key) const {
ERR_FAIL_INDEX_V(p_track, tracks.size(), 0);
const Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_AUDIO, 0);
@@ -2426,7 +2426,7 @@ float Animation::audio_track_get_key_end_offset(int p_track, int p_key) const {
//
-int Animation::animation_track_insert_key(int p_track, float p_time, const StringName &p_animation) {
+int Animation::animation_track_insert_key(int p_track, double p_time, const StringName &p_animation) {
ERR_FAIL_INDEX_V(p_track, tracks.size(), -1);
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_ANIMATION, -1);
@@ -2470,7 +2470,7 @@ StringName Animation::animation_track_get_key_animation(int p_track, int p_key)
return at->values[p_key].value;
}
-void Animation::set_length(float p_length) {
+void Animation::set_length(real_t p_length) {
if (p_length < ANIM_MIN_LENGTH) {
p_length = ANIM_MIN_LENGTH;
}
@@ -2478,7 +2478,7 @@ void Animation::set_length(float p_length) {
emit_changed();
}
-float Animation::get_length() const {
+real_t Animation::get_length() const {
return length;
}
@@ -2558,12 +2558,12 @@ void Animation::track_swap(int p_track, int p_with_track) {
emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
-void Animation::set_step(float p_step) {
+void Animation::set_step(real_t p_step) {
step = p_step;
emit_changed();
}
-float Animation::get_step() const {
+real_t Animation::get_step() const {
return step;
}
@@ -2708,7 +2708,7 @@ void Animation::clear() {
emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
-bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm) {
+bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, real_t p_alowed_linear_err, real_t p_alowed_angular_err, real_t p_max_optimizable_angle, const Vector3 &p_norm) {
real_t c = (t1.time - t0.time) / (t2.time - t0.time);
real_t t[3] = { -1, -1, -1 };
@@ -2727,9 +2727,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
} else {
Vector3 pd = (v2 - v0);
- float d0 = pd.dot(v0);
- float d1 = pd.dot(v1);
- float d2 = pd.dot(v2);
+ real_t d0 = pd.dot(v0);
+ real_t d1 = pd.dot(v1);
+ real_t d2 = pd.dot(v2);
if (d1 < d0 || d1 > d2) {
return false;
}
@@ -2817,9 +2817,9 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
} else {
Vector3 pd = (v2 - v0);
- float d0 = pd.dot(v0);
- float d1 = pd.dot(v1);
- float d2 = pd.dot(v2);
+ real_t d0 = pd.dot(v0);
+ real_t d1 = pd.dot(v1);
+ real_t d2 = pd.dot(v2);
if (d1 < d0 || d1 > d2) {
return false; //beyond segment range
}
@@ -2875,7 +2875,7 @@ bool Animation::_transform_track_optimize_key(const TKey<TransformKey> &t0, cons
return erase;
}
-void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
+void Animation::_transform_track_optimize(int p_idx, real_t p_allowed_linear_err, real_t p_allowed_angular_err, real_t p_max_optimizable_angle) {
ERR_FAIL_INDEX(p_idx, tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type != TYPE_TRANSFORM3D);
TransformTrack *tt = static_cast<TransformTrack *>(tracks[p_idx]);
@@ -2915,7 +2915,7 @@ void Animation::_transform_track_optimize(int p_idx, float p_allowed_linear_err,
}
}
-void Animation::optimize(float p_allowed_linear_err, float p_allowed_angular_err, float p_max_optimizable_angle) {
+void Animation::optimize(real_t p_allowed_linear_err, real_t p_allowed_angular_err, real_t p_max_optimizable_angle) {
for (int i = 0; i < tracks.size(); i++) {
if (tracks[i]->type == TYPE_TRANSFORM3D) {
_transform_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err, p_max_optimizable_angle);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 920ee2e5ab..6227f6967f 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -76,8 +76,8 @@ private:
};
struct Key {
- float transition = 1.0;
- float time = 0.0; // time in secs
+ real_t transition = 1.0;
+ double time = 0.0; // time in secs
};
// transform key holds either Vector3 or Quaternion
@@ -129,7 +129,7 @@ private:
struct BezierKey {
Vector2 in_handle; //relative (x always <0)
Vector2 out_handle; //relative (x always >0)
- float value = 0.0;
+ real_t value = 0.0;
};
struct BezierTrack : public Track {
@@ -144,8 +144,8 @@ private:
struct AudioKey {
RES stream;
- float start_offset = 0.0; //offset from start
- float end_offset = 0.0; //offset from end, if 0 then full length or infinite
+ real_t start_offset = 0.0; //offset from start
+ real_t end_offset = 0.0; //offset from end, if 0 then full length or infinite
AudioKey() {
}
};
@@ -172,46 +172,46 @@ private:
/*
template<class T>
- int _insert_pos(float p_time, T& p_keys);*/
+ int _insert_pos(double p_time, T& p_keys);*/
template <class T>
void _clear(T &p_keys);
template <class T, class V>
- int _insert(float p_time, T &p_keys, const V &p_value);
+ int _insert(double p_time, T &p_keys, const V &p_value);
template <class K>
- inline int _find(const Vector<K> &p_keys, float p_time) const;
+ inline int _find(const Vector<K> &p_keys, double p_time) const;
- _FORCE_INLINE_ Animation::TransformKey _interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, float p_c) const;
+ _FORCE_INLINE_ Animation::TransformKey _interpolate(const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, real_t p_c) const;
- _FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, float p_c) const;
- _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, float p_c) const;
- _FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, float p_c) const;
- _FORCE_INLINE_ float _interpolate(const float &p_a, const float &p_b, float p_c) const;
+ _FORCE_INLINE_ Vector3 _interpolate(const Vector3 &p_a, const Vector3 &p_b, real_t p_c) const;
+ _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const;
+ _FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const;
+ _FORCE_INLINE_ real_t _interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const;
- _FORCE_INLINE_ Animation::TransformKey _cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, float p_c) const;
- _FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, float p_c) const;
- _FORCE_INLINE_ Quaternion _cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, float p_c) const;
- _FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, float p_c) const;
- _FORCE_INLINE_ float _cubic_interpolate(const float &p_pre_a, const float &p_a, const float &p_b, const float &p_post_b, float p_c) const;
+ _FORCE_INLINE_ Animation::TransformKey _cubic_interpolate(const Animation::TransformKey &p_pre_a, const Animation::TransformKey &p_a, const Animation::TransformKey &p_b, const Animation::TransformKey &p_post_b, real_t p_c) const;
+ _FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const;
+ _FORCE_INLINE_ Quaternion _cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const;
+ _FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const;
+ _FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const;
template <class T>
- _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, float p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const;
+ _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok) const;
template <class T>
- _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, float from_time, float to_time, List<int> *p_indices) const;
+ _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const;
- _FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const;
- _FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, float from_time, float to_time, List<int> *p_indices) const;
+ _FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const;
+ _FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const;
- float length = 1.0;
- float step = 0.1;
+ double length = 1.0;
+ real_t step = 0.1;
bool loop = false;
// bind helpers
private:
- Array _transform_track_interpolate(int p_track, float p_time) const {
+ Array _transform_track_interpolate(int p_track, double p_time) const {
Vector3 loc;
Quaternion rot;
Vector3 scale;
@@ -223,7 +223,7 @@ private:
return ret;
}
- Vector<int> _value_track_get_key_indices(int p_track, float p_time, float p_delta) const {
+ Vector<int> _value_track_get_key_indices(int p_track, double p_time, double p_delta) const {
List<int> idxs;
value_track_get_key_indices(p_track, p_time, p_delta, &idxs);
Vector<int> idxr;
@@ -233,7 +233,7 @@ private:
}
return idxr;
}
- Vector<int> _method_track_get_key_indices(int p_track, float p_time, float p_delta) const {
+ Vector<int> _method_track_get_key_indices(int p_track, double p_time, double p_delta) const {
List<int> idxs;
method_track_get_key_indices(p_track, p_time, p_delta, &idxs);
Vector<int> idxr;
@@ -244,8 +244,8 @@ private:
return idxr;
}
- bool _transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, float p_alowed_linear_err, float p_alowed_angular_err, float p_max_optimizable_angle, const Vector3 &p_norm);
- void _transform_track_optimize(int p_idx, float p_allowed_linear_err = 0.05, float p_allowed_angular_err = 0.01, float p_max_optimizable_angle = Math_PI * 0.125);
+ bool _transform_track_optimize_key(const TKey<TransformKey> &t0, const TKey<TransformKey> &t1, const TKey<TransformKey> &t2, real_t p_alowed_linear_err, real_t p_alowed_angular_err, real_t p_max_optimizable_angle, const Vector3 &p_norm);
+ void _transform_track_optimize(int p_idx, real_t p_allowed_linear_err = 0.05, real_t p_allowed_angular_err = 0.01, real_t p_max_optimizable_angle = Math_PI * 0.125);
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -279,75 +279,75 @@ public:
void track_set_enabled(int p_track, bool p_enabled);
bool track_is_enabled(int p_track) const;
- void track_insert_key(int p_track, float p_time, const Variant &p_key, float p_transition = 1);
- void track_set_key_transition(int p_track, int p_key_idx, float p_transition);
+ void track_insert_key(int p_track, double p_time, const Variant &p_key, real_t p_transition = 1);
+ void track_set_key_transition(int p_track, int p_key_idx, real_t p_transition);
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
- void track_set_key_time(int p_track, int p_key_idx, float p_time);
- int track_find_key(int p_track, float p_time, bool p_exact = false) const;
+ void track_set_key_time(int p_track, int p_key_idx, double p_time);
+ int track_find_key(int p_track, double p_time, bool p_exact = false) const;
void track_remove_key(int p_track, int p_idx);
- void track_remove_key_at_time(int p_track, float p_time);
+ void track_remove_key_at_time(int p_track, double p_time);
int track_get_key_count(int p_track) const;
Variant track_get_key_value(int p_track, int p_key_idx) const;
- float track_get_key_time(int p_track, int p_key_idx) const;
- float track_get_key_transition(int p_track, int p_key_idx) const;
+ double track_get_key_time(int p_track, int p_key_idx) const;
+ real_t track_get_key_transition(int p_track, int p_key_idx) const;
- int transform_track_insert_key(int p_track, float p_time, const Vector3 &p_loc, const Quaternion &p_rot = Quaternion(), const Vector3 &p_scale = Vector3());
+ int transform_track_insert_key(int p_track, double p_time, const Vector3 &p_loc, const Quaternion &p_rot = Quaternion(), const Vector3 &p_scale = Vector3());
Error transform_track_get_key(int p_track, int p_key, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
void track_set_interpolation_type(int p_track, InterpolationType p_interp);
InterpolationType track_get_interpolation_type(int p_track) const;
- int bezier_track_insert_key(int p_track, float p_time, float p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle);
- void bezier_track_set_key_value(int p_track, int p_index, float p_value);
+ int bezier_track_insert_key(int p_track, double p_time, real_t p_value, const Vector2 &p_in_handle, const Vector2 &p_out_handle);
+ void bezier_track_set_key_value(int p_track, int p_index, real_t p_value);
void bezier_track_set_key_in_handle(int p_track, int p_index, const Vector2 &p_handle);
void bezier_track_set_key_out_handle(int p_track, int p_index, const Vector2 &p_handle);
- float bezier_track_get_key_value(int p_track, int p_index) const;
+ real_t bezier_track_get_key_value(int p_track, int p_index) const;
Vector2 bezier_track_get_key_in_handle(int p_track, int p_index) const;
Vector2 bezier_track_get_key_out_handle(int p_track, int p_index) const;
- float bezier_track_interpolate(int p_track, float p_time) const;
+ real_t bezier_track_interpolate(int p_track, double p_time) const;
- int audio_track_insert_key(int p_track, float p_time, const RES &p_stream, float p_start_offset = 0, float p_end_offset = 0);
+ int audio_track_insert_key(int p_track, double p_time, const RES &p_stream, real_t p_start_offset = 0, real_t p_end_offset = 0);
void audio_track_set_key_stream(int p_track, int p_key, const RES &p_stream);
- void audio_track_set_key_start_offset(int p_track, int p_key, float p_offset);
- void audio_track_set_key_end_offset(int p_track, int p_key, float p_offset);
+ void audio_track_set_key_start_offset(int p_track, int p_key, real_t p_offset);
+ void audio_track_set_key_end_offset(int p_track, int p_key, real_t p_offset);
RES audio_track_get_key_stream(int p_track, int p_key) const;
- float audio_track_get_key_start_offset(int p_track, int p_key) const;
- float audio_track_get_key_end_offset(int p_track, int p_key) const;
+ real_t audio_track_get_key_start_offset(int p_track, int p_key) const;
+ real_t audio_track_get_key_end_offset(int p_track, int p_key) const;
- int animation_track_insert_key(int p_track, float p_time, const StringName &p_animation);
+ int animation_track_insert_key(int p_track, double p_time, const StringName &p_animation);
void animation_track_set_key_animation(int p_track, int p_key, const StringName &p_animation);
StringName animation_track_get_key_animation(int p_track, int p_key) const;
void track_set_interpolation_loop_wrap(int p_track, bool p_enable);
bool track_get_interpolation_loop_wrap(int p_track) const;
- Error transform_track_interpolate(int p_track, float p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
+ Error transform_track_interpolate(int p_track, double p_time, Vector3 *r_loc, Quaternion *r_rot, Vector3 *r_scale) const;
- Variant value_track_interpolate(int p_track, float p_time) const;
- void value_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
+ Variant value_track_interpolate(int p_track, double p_time) const;
+ void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
void value_track_set_update_mode(int p_track, UpdateMode p_mode);
UpdateMode value_track_get_update_mode(int p_track) const;
- void method_track_get_key_indices(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
+ void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const;
StringName method_track_get_name(int p_track, int p_key_idx) const;
void copy_track(int p_track, Ref<Animation> p_to_animation);
- void track_get_key_indices_in_range(int p_track, float p_time, float p_delta, List<int> *p_indices) const;
+ void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices) const;
- void set_length(float p_length);
- float get_length() const;
+ void set_length(real_t p_length);
+ real_t get_length() const;
void set_loop(bool p_enabled);
bool has_loop() const;
- void set_step(float p_step);
- float get_step() const;
+ void set_step(real_t p_step);
+ real_t get_step() const;
void clear();
- void optimize(float p_allowed_linear_err = 0.05, float p_allowed_angular_err = 0.01, float p_max_optimizable_angle = Math_PI * 0.125);
+ void optimize(real_t p_allowed_linear_err = 0.05, real_t p_allowed_angular_err = 0.01, real_t p_max_optimizable_angle = Math_PI * 0.125);
Animation();
~Animation();
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index c13db83d6d..3b666640f8 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -1366,7 +1366,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const {
frac /= bake_interval;
}
- return Math::lerp(r[idx], r[idx + 1], frac);
+ return Math::lerp(r[idx], r[idx + 1], (real_t)frac);
}
Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const {
@@ -1424,7 +1424,7 @@ PackedVector3Array Curve3D::get_baked_points() const {
return baked_point_cache;
}
-PackedFloat32Array Curve3D::get_baked_tilts() const {
+Vector<real_t> Curve3D::get_baked_tilts() const {
if (baked_cache_dirty) {
_bake();
}
@@ -1545,7 +1545,7 @@ Dictionary Curve3D::_get_data() const {
PackedVector3Array d;
d.resize(points.size() * 3);
Vector3 *w = d.ptrw();
- PackedFloat32Array t;
+ Vector<real_t> t;
t.resize(points.size());
real_t *wt = t.ptrw();
@@ -1571,7 +1571,7 @@ void Curve3D::_set_data(const Dictionary &p_data) {
ERR_FAIL_COND(pc % 3 != 0);
points.resize(pc / 3);
const Vector3 *r = rp.ptr();
- PackedFloat32Array rtl = p_data["tilts"];
+ Vector<real_t> rtl = p_data["tilts"];
const real_t *rt = rtl.ptr();
for (int i = 0; i < points.size(); i++) {
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 746c6fa597..c25d307608 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -222,7 +222,7 @@ class Curve3D : public Resource {
mutable bool baked_cache_dirty = false;
mutable PackedVector3Array baked_point_cache;
- mutable PackedFloat32Array baked_tilt_cache;
+ mutable Vector<real_t> baked_tilt_cache;
mutable PackedVector3Array baked_up_vector_cache;
mutable float baked_max_ofs = 0.0;
@@ -265,7 +265,7 @@ public:
float interpolate_baked_tilt(float p_offset) const;
Vector3 interpolate_baked_up_vector(float p_offset, bool p_apply_tilt = false) const;
PackedVector3Array get_baked_points() const; //useful for going through
- PackedFloat32Array get_baked_tilts() const; //useful for going through
+ Vector<real_t> get_baked_tilts() const; //useful for going through
PackedVector3Array get_baked_up_vectors() const;
Vector3 get_closest_point(const Vector3 &p_to_point) const;
float get_closest_offset(const Vector3 &p_to_point) const;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index d0dee2b5e3..efc37709a5 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -863,6 +863,8 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("bar_arrow", "ColorPicker", make_icon(bar_arrow_png));
theme->set_icon("picker_cursor", "ColorPicker", make_icon(picker_cursor_png));
+ // ColorPickerButton
+
theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png));
// TooltipPanel
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index cdb1bc527b..97e64e4746 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -50,10 +50,6 @@ static const unsigned char checked_disabled_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x3, 0x0, 0x0, 0x0, 0x28, 0x2d, 0xf, 0x53, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x99, 0x50, 0x4c, 0x54, 0x45, 0x0, 0x0, 0x0, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x73, 0x72, 0x7b, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x7a, 0x78, 0x83, 0x82, 0x80, 0x8a, 0x90, 0x90, 0x93, 0x6a, 0x69, 0x70, 0x6a, 0x68, 0x70, 0x93, 0x93, 0x95, 0x58, 0x58, 0x5c, 0x58, 0x58, 0x5b, 0x7d, 0x7d, 0x7f, 0x58, 0x58, 0x5b, 0xa4, 0xa4, 0xa4, 0x9e, 0x9e, 0xa0, 0x9e, 0x9e, 0x9e, 0x9b, 0x9b, 0x9c, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x93, 0x93, 0x94, 0x8f, 0x8f, 0x8f, 0x86, 0x86, 0x88, 0x85, 0x85, 0x86, 0x82, 0x82, 0x83, 0x81, 0x81, 0x83, 0x7f, 0x7f, 0x81, 0x7c, 0x7c, 0x7e, 0x7a, 0x7a, 0x7d, 0x78, 0x78, 0x7b, 0x71, 0x71, 0x74, 0x68, 0x68, 0x6c, 0x66, 0x66, 0x6a, 0x65, 0x65, 0x68, 0x63, 0x63, 0x66, 0x5f, 0x5f, 0x63, 0x5c, 0x5c, 0x60, 0x5c, 0x5c, 0x5f, 0x5a, 0x5a, 0x5e, 0x59, 0x59, 0x5d, 0x59, 0x59, 0x5c, 0x58, 0x58, 0x5b, 0x57, 0x57, 0x5a, 0x56, 0x56, 0x59, 0x10, 0x13, 0xbb, 0xf, 0x0, 0x0, 0x0, 0x10, 0x74, 0x52, 0x4e, 0x53, 0x0, 0x7, 0x27, 0x27, 0x50, 0x66, 0x68, 0x6a, 0x81, 0xb4, 0xb4, 0xdd, 0xfa, 0xfa, 0xfb, 0xfb, 0x5b, 0xd1, 0xf1, 0xe6, 0x0, 0x0, 0x0, 0x96, 0x49, 0x44, 0x41, 0x54, 0x78, 0x5e, 0x5d, 0x8f, 0xc9, 0x12, 0x82, 0x30, 0x14, 0x4, 0x87, 0x18, 0x50, 0x51, 0x44, 0x25, 0x42, 0x4, 0x77, 0xc4, 0x8d, 0x97, 0x0, 0xf9, 0xff, 0x8f, 0xb3, 0x88, 0xa4, 0x4a, 0xed, 0x63, 0x5f, 0xa6, 0x7, 0xf8, 0x7, 0x1e, 0xe3, 0x7e, 0x60, 0x19, 0x4f, 0x46, 0x1e, 0x0, 0x36, 0x8d, 0x4c, 0x67, 0x59, 0x65, 0x33, 0x6, 0x80, 0x47, 0xad, 0x56, 0x3d, 0xb7, 0x3c, 0x5d, 0x70, 0x0, 0xbe, 0xd1, 0x44, 0x65, 0x4d, 0x94, 0xc8, 0xc2, 0xf8, 0x0, 0x82, 0x4e, 0x91, 0x94, 0x15, 0x5d, 0xd2, 0xec, 0xde, 0x5, 0x83, 0x38, 0xc8, 0xe3, 0x63, 0x23, 0xce, 0xca, 0x9, 0x7a, 0x6e, 0xf3, 0x93, 0x48, 0x1a, 0x27, 0x14, 0x35, 0x3b, 0xb9, 0x5e, 0x56, 0xe4, 0x84, 0x22, 0xba, 0xa, 0x51, 0xd0, 0xb7, 0xa8, 0xcb, 0xfd, 0xcb, 0x9, 0x3b, 0xfb, 0x41, 0xdb, 0x59, 0x17, 0xa6, 0x94, 0x6e, 0xe3, 0x3e, 0x8c, 0x85, 0xf1, 0x90, 0x6e, 0xe6, 0x21, 0xfb, 0x39, 0xe7, 0x73, 0xe6, 0xfd, 0x5f, 0x7, 0xde, 0xc3, 0xb5, 0x16, 0x87, 0xb0, 0x9e, 0x42, 0x46, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char checker_bg_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0xe1, 0x64, 0xe1, 0x57, 0x0, 0x0, 0x0, 0x14, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xfc, 0xcf, 0xc0, 0xc0, 0xd0, 0x0, 0xc4, 0xf8, 0x18, 0xf5, 0x84, 0x19, 0x0, 0x9f, 0x5f, 0xa, 0x1, 0xf8, 0xef, 0x65, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
static const unsigned char close_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0x62, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0xa0, 0x16, 0xe0, 0x8c, 0xe0, 0x11, 0x43, 0xe6, 0xf3, 0x88, 0x71, 0x46, 0xa0, 0x48, 0x73, 0xfc, 0xe3, 0xb8, 0xcc, 0x23, 0x86, 0x90, 0xe6, 0xb8, 0xcc, 0xf1, 0xf, 0x49, 0x9, 0x8f, 0x28, 0xe7, 0x25, 0x8e, 0xff, 0x1c, 0xd7, 0xb9, 0x24, 0x91, 0x79, 0xdc, 0x12, 0x40, 0xe, 0xa6, 0x12, 0x54, 0x69, 0x4c, 0x25, 0xb7, 0x38, 0xae, 0x21, 0xa4, 0x31, 0x94, 0x80, 0x24, 0x81, 0xf0, 0x36, 0x48, 0x1a, 0xaf, 0x2, 0x88, 0x5b, 0xf0, 0x5a, 0x81, 0xa1, 0x4, 0xe1, 0x34, 0x84, 0x73, 0xb1, 0x4a, 0xa3, 0x7b, 0x9a, 0x70, 0x40, 0x11, 0xe, 0x6a, 0xca, 0x1, 0x0, 0x2a, 0x28, 0x37, 0x83, 0x3e, 0x27, 0xb0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
diff --git a/scene/resources/height_map_shape_3d.cpp b/scene/resources/height_map_shape_3d.cpp
index de5da944bc..d1a958ad38 100644
--- a/scene/resources/height_map_shape_3d.cpp
+++ b/scene/resources/height_map_shape_3d.cpp
@@ -41,7 +41,7 @@ Vector<Vector3> HeightMapShape3D::get_debug_mesh_lines() const {
Vector2 size(map_width - 1, map_depth - 1);
Vector2 start = size * -0.5;
- const float *r = map_data.ptr();
+ const real_t *r = map_data.ptr();
// reserve some memory for our points..
points.resize(((map_width - 1) * map_depth * 2) + (map_width * (map_depth - 1) * 2) + ((map_width - 1) * (map_depth - 1) * 2));
@@ -105,7 +105,7 @@ void HeightMapShape3D::set_map_width(int p_new) {
int new_size = map_width * map_depth;
map_data.resize(map_width * map_depth);
- float *w = map_data.ptrw();
+ real_t *w = map_data.ptrw();
while (was_size < new_size) {
w[was_size++] = 0.0;
}
@@ -129,7 +129,7 @@ void HeightMapShape3D::set_map_depth(int p_new) {
int new_size = map_width * map_depth;
map_data.resize(new_size);
- float *w = map_data.ptrw();
+ real_t *w = map_data.ptrw();
while (was_size < new_size) {
w[was_size++] = 0.0;
}
@@ -143,7 +143,7 @@ int HeightMapShape3D::get_map_depth() const {
return map_depth;
}
-void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) {
+void HeightMapShape3D::set_map_data(Vector<real_t> p_new) {
int size = (map_width * map_depth);
if (p_new.size() != size) {
// fail
@@ -151,10 +151,10 @@ void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) {
}
// copy
- float *w = map_data.ptrw();
- const float *r = p_new.ptr();
+ real_t *w = map_data.ptrw();
+ const real_t *r = p_new.ptr();
for (int i = 0; i < size; i++) {
- float val = r[i];
+ real_t val = r[i];
w[i] = val;
if (i == 0) {
min_height = val;
@@ -174,7 +174,7 @@ void HeightMapShape3D::set_map_data(PackedFloat32Array p_new) {
notify_change_to_owners();
}
-PackedFloat32Array HeightMapShape3D::get_map_data() const {
+Vector<real_t> HeightMapShape3D::get_map_data() const {
return map_data;
}
@@ -194,7 +194,7 @@ void HeightMapShape3D::_bind_methods() {
HeightMapShape3D::HeightMapShape3D() :
Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_HEIGHTMAP)) {
map_data.resize(map_width * map_depth);
- float *w = map_data.ptrw();
+ real_t *w = map_data.ptrw();
w[0] = 0.0;
w[1] = 0.0;
w[2] = 0.0;
diff --git a/scene/resources/height_map_shape_3d.h b/scene/resources/height_map_shape_3d.h
index 1219791c56..1273aee040 100644
--- a/scene/resources/height_map_shape_3d.h
+++ b/scene/resources/height_map_shape_3d.h
@@ -38,7 +38,7 @@ class HeightMapShape3D : public Shape3D {
int map_width = 2;
int map_depth = 2;
- PackedFloat32Array map_data;
+ Vector<real_t> map_data;
real_t min_height = 0.0;
real_t max_height = 0.0;
@@ -51,8 +51,8 @@ public:
int get_map_width() const;
void set_map_depth(int p_new);
int get_map_depth() const;
- void set_map_data(PackedFloat32Array p_new);
- PackedFloat32Array get_map_data() const;
+ void set_map_data(Vector<real_t> p_new);
+ Vector<real_t> get_map_data() const;
virtual Vector<Vector3> get_debug_mesh_lines() const override;
virtual real_t get_enclosing_radius() const override;
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 2f92872ad5..ad589a605e 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -653,6 +653,7 @@ enum OldArrayFormat {
};
+#ifndef DISABLE_DEPRECATED
static Array _convert_old_array(const Array &p_old) {
Array new_array;
new_array.resize(Mesh::ARRAY_MAX);
@@ -677,6 +678,7 @@ static Mesh::PrimitiveType _old_primitives[7] = {
Mesh::PRIMITIVE_TRIANGLE_STRIP,
Mesh::PRIMITIVE_TRIANGLE_STRIP
};
+#endif // DISABLE_DEPRECATED
void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) {
uint32_t dst_vertex_stride;
diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp
index 3fb4f8f211..04b2437ae8 100644
--- a/scene/resources/mesh_data_tool.cpp
+++ b/scene/resources/mesh_data_tool.cpp
@@ -107,9 +107,9 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf
bo = arrays[Mesh::ARRAY_BONES].operator Vector<int>().ptr();
}
- const real_t *we = nullptr;
+ const float *we = nullptr;
if (arrays[Mesh::ARRAY_WEIGHTS].get_type() != Variant::NIL) {
- we = arrays[Mesh::ARRAY_WEIGHTS].operator Vector<real_t>().ptr();
+ we = arrays[Mesh::ARRAY_WEIGHTS].operator Vector<float>().ptr();
}
vertices.resize(vcount);
diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp
index a08684a506..4dd3c874cb 100644
--- a/scene/resources/polygon_path_finder.cpp
+++ b/scene/resources/polygon_path_finder.cpp
@@ -417,9 +417,9 @@ void PolygonPathFinder::_set_data(const Dictionary &p_data) {
}
if (p_data.has("penalties")) {
- Vector<float> penalties = p_data["penalties"];
+ Vector<real_t> penalties = p_data["penalties"];
if (penalties.size() == pc) {
- const float *pr2 = penalties.ptr();
+ const real_t *pr2 = penalties.ptr();
for (int i = 0; i < pc; i++) {
points.write[i].penalty = pr2[i];
}
@@ -445,11 +445,11 @@ Dictionary PolygonPathFinder::_get_data() const {
p.resize(MAX(0, points.size() - 2));
connections.resize(MAX(0, points.size() - 2));
ind.resize(edges.size() * 2);
- Vector<float> penalties;
+ Vector<real_t> penalties;
penalties.resize(MAX(0, points.size() - 2));
{
Vector2 *wp = p.ptrw();
- float *pw = penalties.ptrw();
+ real_t *pw = penalties.ptrw();
for (int i = 0; i < points.size() - 2; i++) {
wp[i] = points[i].pos;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 2b93414906..dbe118a262 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -558,6 +558,12 @@ Error ResourceLoaderText::load() {
resource_current++;
+ int_resources[id] = res; //always assign int resources
+ if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
+ res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
+ res->set_scene_unique_id(id);
+ }
+
while (true) {
String assign;
Variant value;
@@ -585,12 +591,6 @@ Error ResourceLoaderText::load() {
}
}
- int_resources[id] = res; //always assign int resources
- if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
- res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
- res->set_scene_unique_id(id);
- }
-
if (progress && resources_total > 0) {
*progress = resource_current / float(resources_total);
}
diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp
index e9adf67559..140c6f821f 100644
--- a/scene/resources/sprite_frames.cpp
+++ b/scene/resources/sprite_frames.cpp
@@ -122,14 +122,14 @@ Vector<String> SpriteFrames::get_animation_names() const {
return names;
}
-void SpriteFrames::set_animation_speed(const StringName &p_anim, float p_fps) {
+void SpriteFrames::set_animation_speed(const StringName &p_anim, double p_fps) {
ERR_FAIL_COND_MSG(p_fps < 0, "Animation speed cannot be negative (" + itos(p_fps) + ").");
Map<StringName, Anim>::Element *E = animations.find(p_anim);
ERR_FAIL_COND_MSG(!E, "Animation '" + String(p_anim) + "' doesn't exist.");
E->get().speed = p_fps;
}
-float SpriteFrames::get_animation_speed(const StringName &p_anim) const {
+double SpriteFrames::get_animation_speed(const StringName &p_anim) const {
const Map<StringName, Anim>::Element *E = animations.find(p_anim);
ERR_FAIL_COND_V_MSG(!E, 0, "Animation '" + String(p_anim) + "' doesn't exist.");
return E->get().speed;
diff --git a/scene/resources/sprite_frames.h b/scene/resources/sprite_frames.h
index 282c5f20ab..fdfd6af5ab 100644
--- a/scene/resources/sprite_frames.h
+++ b/scene/resources/sprite_frames.h
@@ -37,7 +37,7 @@ class SpriteFrames : public Resource {
GDCLASS(SpriteFrames, Resource);
struct Anim {
- float speed = 5.0;
+ double speed = 5.0;
bool loop = true;
Vector<Ref<Texture2D>> frames;
};
@@ -64,8 +64,8 @@ public:
void get_animation_list(List<StringName> *r_animations) const;
Vector<String> get_animation_names() const;
- void set_animation_speed(const StringName &p_anim, float p_fps);
- float get_animation_speed(const StringName &p_anim) const;
+ void set_animation_speed(const StringName &p_anim, double p_fps);
+ double get_animation_speed(const StringName &p_anim) const;
void set_animation_loop(const StringName &p_anim, bool p_loop);
bool get_animation_loop(const StringName &p_anim) const;
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index f1eff6e84f..5e60c7c4ed 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -56,8 +56,8 @@ void TextLine::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bidi_override", "override"), &TextLine::_set_bidi_override);
ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextLine::add_string, DEFVAL(Dictionary()), DEFVAL(""));
- ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(VALIGN_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextLine::resize_object, DEFVAL(VALIGN_CENTER));
+ ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextLine::add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextLine::resize_object, DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("set_width", "width"), &TextLine::set_width);
ClassDB::bind_method(D_METHOD("get_width"), &TextLine::get_width);
@@ -175,13 +175,13 @@ bool TextLine::add_string(const String &p_text, const Ref<Font> &p_fonts, int p_
return res;
}
-bool TextLine::add_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) {
+bool TextLine::add_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length);
dirty = true;
return res;
}
-bool TextLine::resize_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align) {
+bool TextLine::resize_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
const_cast<TextLine *>(this)->_shape();
return TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align);
}
diff --git a/scene/resources/text_line.h b/scene/resources/text_line.h
index 1b5c1a3123..b773bd05be 100644
--- a/scene/resources/text_line.h
+++ b/scene/resources/text_line.h
@@ -76,8 +76,8 @@ public:
bool get_preserve_control() const;
bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
- bool add_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1);
- bool resize_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER);
+ bool add_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1);
+ bool resize_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER);
void set_align(HAlign p_align);
HAlign get_align() const;
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index 958c94fe31..ffae551570 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -59,8 +59,8 @@ void TextParagraph::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_dropcap"), &TextParagraph::clear_dropcap);
ClassDB::bind_method(D_METHOD("add_string", "text", "fonts", "size", "opentype_features", "language"), &TextParagraph::add_string, DEFVAL(Dictionary()), DEFVAL(""));
- ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextParagraph::add_object, DEFVAL(VALIGN_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextParagraph::resize_object, DEFVAL(VALIGN_CENTER));
+ ClassDB::bind_method(D_METHOD("add_object", "key", "size", "inline_align", "length"), &TextParagraph::add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("resize_object", "key", "size", "inline_align"), &TextParagraph::resize_object, DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("set_align", "align"), &TextParagraph::set_align);
ClassDB::bind_method(D_METHOD("get_align"), &TextParagraph::get_align);
@@ -290,13 +290,13 @@ void TextParagraph::set_bidi_override(const Vector<Vector2i> &p_override) {
dirty_lines = true;
}
-bool TextParagraph::add_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align, int p_length) {
+bool TextParagraph::add_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) {
bool res = TS->shaped_text_add_object(rid, p_key, p_size, p_inline_align, p_length);
dirty_lines = true;
return res;
}
-bool TextParagraph::resize_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align) {
+bool TextParagraph::resize_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) {
bool res = TS->shaped_text_resize_object(rid, p_key, p_size, p_inline_align);
dirty_lines = true;
return res;
diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h
index a34e745090..d0747a9e03 100644
--- a/scene/resources/text_paragraph.h
+++ b/scene/resources/text_paragraph.h
@@ -86,8 +86,8 @@ public:
void clear_dropcap();
bool add_string(const String &p_text, const Ref<Font> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "");
- bool add_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1);
- bool resize_object(Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER);
+ bool add_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1);
+ bool resize_object(Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER);
void set_align(HAlign p_align);
HAlign get_align() const;
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index a23152a6d1..a6815da6f4 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -1648,19 +1648,10 @@ void VisualShader::_update_shader() const {
{
//fill render mode enums
int idx = 0;
- bool specular = false;
while (render_mode_enums[idx].string) {
if (shader_mode == render_mode_enums[idx].mode) {
- if (shader_mode == Shader::MODE_SPATIAL) {
- if (String(render_mode_enums[idx].string) == "specular") {
- specular = true;
- }
- }
- if (modes.has(render_mode_enums[idx].string) || specular) {
- int which = 0;
- if (modes.has(render_mode_enums[idx].string)) {
- which = modes[render_mode_enums[idx].string];
- }
+ if (modes.has(render_mode_enums[idx].string)) {
+ int which = modes[render_mode_enums[idx].string];
int count = 0;
for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) {
String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i];
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index b4a95651cb..74bef433dc 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -266,6 +266,10 @@ public:
void integrate_forces(real_t p_step);
void integrate_velocities(real_t p_step);
+ _FORCE_INLINE_ Vector2 get_velocity_in_local_point(const Vector2 &rel_pos) const {
+ return linear_velocity + Vector2(-angular_velocity * rel_pos.y, angular_velocity * rel_pos.x);
+ }
+
_FORCE_INLINE_ Vector2 get_motion() const {
if (mode > PhysicsServer2D::BODY_MODE_KINEMATIC) {
return new_transform.get_origin() - get_transform().get_origin();
@@ -352,6 +356,8 @@ public:
virtual void set_transform(const Transform2D &p_transform) override { body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform); }
virtual Transform2D get_transform() const override { return body->get_transform(); }
+ virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
+
virtual void add_central_force(const Vector2 &p_force) override { body->add_central_force(p_force); }
virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) override { body->add_force(p_force, p_position); }
virtual void add_torque(real_t p_torque) override { body->add_torque(p_torque); }
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index 0fa31c5037..bdc615ab6c 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -389,6 +389,8 @@ public:
virtual void set_transform(const Transform3D &p_transform) override { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); }
virtual Transform3D get_transform() const override { return body->get_transform(); }
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const override { return body->get_velocity_in_local_point(p_position); }
+
virtual void add_central_force(const Vector3 &p_force) override { body->add_central_force(p_force); }
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) override {
body->add_force(p_force, p_position);
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index c1a9d6259d..e2ab84428b 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -854,7 +854,7 @@ void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) {
body->set_ray_pickable(p_enable);
}
-bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
@@ -862,7 +862,7 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform3D &p_from,
_update_shapes();
- return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+ return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
}
int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 0ccd15fbb2..326b6fbe7a 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -242,7 +242,7 @@ public:
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override;
virtual int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
// this function only works on physics process, errors and returns null otherwise
diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_3d/physics_server_3d_wrap_mt.h
index 9beec22bcd..c3c2e50e56 100644
--- a/servers/physics_3d/physics_server_3d_wrap_mt.h
+++ b/servers/physics_3d/physics_server_3d_wrap_mt.h
@@ -250,9 +250,9 @@ public:
FUNC2(body_set_ray_pickable, RID, bool);
- bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override {
+ bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) override {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
- return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
+ return physics_3d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes, p_exclude);
}
int body_test_ray_separation(RID p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override {
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index 04a174f9c8..5b3721861e 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -1635,7 +1635,7 @@ ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() {
/* HEIGHT MAP SHAPE */
-Vector<float> HeightMapShape3DSW::get_heights() const {
+Vector<real_t> HeightMapShape3DSW::get_heights() const {
return heights;
}
@@ -1932,7 +1932,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const {
(p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y));
}
-void HeightMapShape3DSW::_setup(const Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
+void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) {
heights = p_heights;
width = p_width;
depth = p_depth;
@@ -1966,8 +1966,12 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
ERR_FAIL_COND(depth <= 0.0);
Variant heights_variant = d["heights"];
- Vector<float> heights_buffer;
+ Vector<real_t> heights_buffer;
+#ifdef REAL_T_IS_DOUBLE
+ if (heights_variant.get_type() == Variant::PACKED_FLOAT64_ARRAY) {
+#else
if (heights_variant.get_type() == Variant::PACKED_FLOAT32_ARRAY) {
+#endif
// Ready-to-use heights can be passed.
heights_buffer = heights_variant;
} else if (heights_variant.get_type() == Variant::OBJECT) {
@@ -1980,13 +1984,17 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) {
PackedByteArray im_data = image->get_data();
heights_buffer.resize(image->get_width() * image->get_height());
- float *w = heights_buffer.ptrw();
- float *rp = (float *)im_data.ptr();
+ real_t *w = heights_buffer.ptrw();
+ real_t *rp = (real_t *)im_data.ptr();
for (int i = 0; i < heights_buffer.size(); ++i) {
w[i] = rp[i];
}
} else {
+#ifdef REAL_T_IS_DOUBLE
+ ERR_FAIL_MSG("Expected PackedFloat64Array or float Image.");
+#else
ERR_FAIL_MSG("Expected PackedFloat32Array or float Image.");
+#endif
}
// Compute min and max heights or use precomputed values.
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index 0d1b7cc3d7..72be34b788 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -389,12 +389,12 @@ public:
};
struct HeightMapShape3DSW : public ConcaveShape3DSW {
- Vector<float> heights;
+ Vector<real_t> heights;
int width = 0;
int depth = 0;
Vector3 local_origin;
- _FORCE_INLINE_ float _get_height(int p_x, int p_z) const {
+ _FORCE_INLINE_ real_t _get_height(int p_x, int p_z) const {
return heights[(p_z * width) + p_x];
}
@@ -406,10 +406,10 @@ struct HeightMapShape3DSW : public ConcaveShape3DSW {
void _get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const;
- void _setup(const Vector<float> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
+ void _setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height);
public:
- Vector<float> get_heights() const;
+ Vector<real_t> get_heights() const;
int get_width() const;
int get_depth() const;
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 1037243d3b..2a39a9d363 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -720,7 +720,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_t
return rays_found;
}
-bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) {
+bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude) {
//give me back regular physics engine logic
//this is madness
//and most people using this function will think
@@ -801,6 +801,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
@@ -890,6 +893,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
@@ -1015,6 +1021,9 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform3D &p_from, co
for (int i = 0; i < amount; i++) {
const CollisionObject3DSW *col_obj = intersection_query_results[i];
+ if (p_exclude.has(col_obj->get_self())) {
+ continue;
+ }
int shape_idx = intersection_query_subindex_results[i];
if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) {
diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h
index 18e93c90cc..580693deba 100644
--- a/servers/physics_3d/space_3d_sw.h
+++ b/servers/physics_3d/space_3d_sw.h
@@ -204,7 +204,7 @@ public:
uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; }
int test_body_ray_separation(Body3DSW *p_body, const Transform3D &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
- bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
+ bool test_body_motion(Body3DSW *p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes, const Set<RID> &p_exclude = Set<RID>());
Space3DSW();
~Space3DSW();
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index e8272f377e..2e44a1a10b 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -89,6 +89,8 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState2D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState2D::get_transform);
+ ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState2D::get_velocity_at_local_position);
+
ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force);
ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState2D::add_force, Vector2());
ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 8542b54838..fafde62599 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -60,6 +60,8 @@ public:
virtual void set_transform(const Transform2D &p_transform) = 0;
virtual Transform2D get_transform() const = 0;
+ virtual Vector2 get_velocity_at_local_position(const Vector2 &p_position) const = 0;
+
virtual void add_central_force(const Vector2 &p_force) = 0;
virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
virtual void add_torque(real_t p_torque) = 0;
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 3ed8841119..b4ee5fbaf0 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -91,6 +91,8 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState3D::get_transform);
+ ClassDB::bind_method(D_METHOD("get_velocity_at_local_position", "local_position"), &PhysicsDirectBodyState3D::get_velocity_at_local_position);
+
ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force, Vector3());
ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force, Vector3());
ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque);
@@ -445,12 +447,16 @@ void PhysicsTestMotionResult3D::_bind_methods() {
///////////////////////////////////////
-bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result) {
+bool PhysicsServer3D::_body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult3D> &p_result, bool p_exclude_raycast_shapes, const Vector<RID> &p_exclude) {
MotionResult *r = nullptr;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
}
- return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r);
+ Set<RID> exclude;
+ for (int i = 0; i < p_exclude.size(); i++) {
+ exclude.insert(p_exclude[i]);
+ }
+ return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes, exclude);
}
RID PhysicsServer3D::shape_create(ShapeType p_shape) {
@@ -606,7 +612,7 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable);
- ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result", "exclude_raycast_shapes", "exclude"), &PhysicsServer3D::_body_test_motion, DEFVAL(0.001), DEFVAL(Variant()), DEFVAL(true), DEFVAL(Array()));
ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state);
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 17bae9a057..0d3d5bd4a1 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -62,6 +62,8 @@ public:
virtual void set_transform(const Transform3D &p_transform) = 0;
virtual Transform3D get_transform() const = 0;
+ virtual Vector3 get_velocity_at_local_position(const Vector3 &p_position) const = 0;
+
virtual void add_central_force(const Vector3 &p_force) = 0;
virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0;
virtual void add_torque(const Vector3 &p_torque) = 0;
@@ -210,7 +212,7 @@ class PhysicsServer3D : public Object {
static PhysicsServer3D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>());
+ virtual bool _body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, const Ref<PhysicsTestMotionResult3D> &p_result = Ref<PhysicsTestMotionResult3D>(), bool p_exclude_raycast_shapes = true, const Vector<RID> &p_exclude = Vector<RID>());
protected:
static void _bind_methods();
@@ -489,7 +491,7 @@ public:
Variant collider_metadata;
};
- virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform3D &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true, const Set<RID> &p_exclude = Set<RID>()) = 0;
struct SeparationResult {
real_t collision_depth;
diff --git a/servers/rendering/rasterizer_dummy.h b/servers/rendering/rasterizer_dummy.h
index b7cf0983af..b2fffca3ea 100644
--- a/servers/rendering/rasterizer_dummy.h
+++ b/servers/rendering/rasterizer_dummy.h
@@ -540,13 +540,13 @@ public:
void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
void particles_set_emitting(RID p_particles, bool p_emitting) override {}
void particles_set_amount(RID p_particles, int p_amount) override {}
- void particles_set_lifetime(RID p_particles, float p_lifetime) override {}
+ void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
- void particles_set_pre_process_time(RID p_particles, float p_time) override {}
+ void particles_set_pre_process_time(RID p_particles, double p_time) override {}
void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) override {}
void particles_set_randomness_ratio(RID p_particles, float p_ratio) override {}
void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
- void particles_set_speed_scale(RID p_particles, float p_scale) override {}
+ void particles_set_speed_scale(RID p_particles, double p_scale) override {}
void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
void particles_set_process_material(RID p_particles, RID p_material) override {}
void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
@@ -724,7 +724,7 @@ public:
class RasterizerDummy : public RendererCompositor {
private:
uint64_t frame = 1;
- float delta = 0;
+ double delta = 0;
protected:
RasterizerCanvasDummy canvas;
@@ -765,7 +765,7 @@ public:
bool is_low_end() const override { return true; }
uint64_t get_frame_number() const override { return frame; }
- float get_frame_delta_time() const override { return delta; }
+ double get_frame_delta_time() const override { return delta; }
RasterizerDummy() {}
~RasterizerDummy() {}
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index ec0a8347f8..fd7d5b91fa 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -639,17 +639,19 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
j2 = j + 1;
- Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+ Vector2 dir = (t + prev_t).normalized();
+ Vector2 tangent = dir * p_width * 0.5;
+ Vector2 border = dir * 2.0;
Vector2 pos = p_points[i];
points_ptr[j] = pos + tangent;
points_ptr[j2] = pos - tangent;
- points_top_ptr[j] = pos + tangent + tangent;
+ points_top_ptr[j] = pos + tangent + border;
points_top_ptr[j2] = pos + tangent;
points_bottom_ptr[j] = pos - tangent;
- points_bottom_ptr[j2] = pos - tangent - tangent;
+ points_bottom_ptr[j2] = pos - tangent - border;
if (i < p_colors.size()) {
color = p_colors[i];
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 5fe9cdffba..6206849b66 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -85,7 +85,7 @@ public:
virtual void end_frame(bool p_swap_buffers) = 0;
virtual void finalize() = 0;
virtual uint64_t get_frame_number() const = 0;
- virtual float get_frame_delta_time() const = 0;
+ virtual double get_frame_delta_time() const = 0;
virtual bool is_low_end() const = 0;
virtual bool is_xr_enabled() const;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 053bda59a7..14b2768c29 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -480,6 +480,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
case Item::Command::TYPE_RECT: {
const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c);
+ if (rect->flags & CANVAS_RECT_TILE) {
+ current_repeat = RenderingServer::CanvasItemTextureRepeat::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED;
+ }
+
//bind pipeline
{
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index 15b3b77ed9..8639362da9 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -80,7 +80,7 @@ protected:
Map<RID, RID> render_target_descriptors;
double time;
- float delta;
+ double delta;
static uint64_t frame;
@@ -100,7 +100,7 @@ public:
void finalize();
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
- _ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; }
+ _ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
_ALWAYS_INLINE_ double get_total_time() const { return time; }
static Error is_viable() {
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 88fe538903..9331cab090 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -1280,12 +1280,11 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1300,12 +1299,11 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::DrawListID cubemap_draw_list;
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1316,12 +1314,11 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
for (int i = 0; i < 6; i++) {
- Transform3D local_view;
- local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]);
+ Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view.basis, multiplier, p_transform.origin);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index d5c7db6fd2..5b845cbb88 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -4091,7 +4091,7 @@ void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
}
-void RendererStorageRD::particles_set_lifetime(RID p_particles, float p_lifetime) {
+void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->lifetime = p_lifetime;
@@ -4103,7 +4103,7 @@ void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot)
particles->one_shot = p_one_shot;
}
-void RendererStorageRD::particles_set_pre_process_time(RID p_particles, float p_time) {
+void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
particles->pre_process_time = p_time;
@@ -4126,7 +4126,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p
particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
}
-void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) {
+void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) {
Particles *particles = particles_owner.getornull(p_particles);
ERR_FAIL_COND(!particles);
@@ -4442,7 +4442,7 @@ void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool
particles->sdf_collision_texture = p_texture;
}
-void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) {
+void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) {
if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -4491,7 +4491,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta
p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
}
- float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0);
+ double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
//move back history (if there is any)
for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
@@ -5131,14 +5131,14 @@ void RendererStorageRD::update_particles() {
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
if (particles->clear && particles->pre_process_time > 0.0) {
- float frame_time;
+ double frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
- float todo = particles->pre_process_time;
+ double todo = particles->pre_process_time;
while (todo >= 0) {
_particles_process(particles, frame_time);
@@ -5147,8 +5147,8 @@ void RendererStorageRD::update_particles() {
}
if (fixed_fps > 0) {
- float frame_time;
- float decr;
+ double frame_time;
+ double decr;
if (zero_time_scale) {
frame_time = 0.0;
decr = 1.0 / fixed_fps;
@@ -5156,13 +5156,13 @@ void RendererStorageRD::update_particles() {
frame_time = 1.0 / fixed_fps;
decr = frame_time;
}
- float delta = RendererCompositorRD::singleton->get_frame_delta_time();
+ double delta = RendererCompositorRD::singleton->get_frame_delta_time();
if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
delta = 0.1;
} else if (delta <= 0.0) { //unlikely but..
delta = 0.001;
}
- float todo = particles->frame_remainder + delta;
+ double todo = particles->frame_remainder + delta;
while (todo >= frame_time) {
_particles_process(particles, frame_time);
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index b290c07705..71c3d8b09a 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -715,12 +715,12 @@ private:
struct Particles {
RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
bool inactive = true;
- float inactive_time = 0.0;
+ double inactive_time = 0.0;
bool emitting = false;
bool one_shot = false;
int amount = 0;
- float lifetime = 1.0;
- float pre_process_time = 0.0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
float explosiveness = 0.0;
float randomness = 0.0;
bool restart_request = false;
@@ -773,12 +773,12 @@ private:
uint32_t cycle_number = 0;
- float speed_scale = 1.0;
+ double speed_scale = 1.0;
int fixed_fps = 30;
bool interpolate = true;
bool fractional_delta = false;
- float frame_remainder = 0;
+ double frame_remainder = 0;
float collision_base_size = 0.01;
bool clear = true;
@@ -805,14 +805,14 @@ private:
}
};
- void _particles_process(Particles *p_particles, float p_delta);
+ void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
void _particles_free_data(Particles *particles);
void _particles_update_buffers(Particles *particles);
struct ParticlesShader {
struct PushConstant {
- float lifetime;
+ double lifetime;
uint32_t clear;
uint32_t total_particles;
uint32_t trail_size;
@@ -2144,13 +2144,13 @@ public:
void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode);
void particles_set_emitting(RID p_particles, bool p_emitting);
void particles_set_amount(RID p_particles, int p_amount);
- void particles_set_lifetime(RID p_particles, float p_lifetime);
+ void particles_set_lifetime(RID p_particles, double p_lifetime);
void particles_set_one_shot(RID p_particles, bool p_one_shot);
- void particles_set_pre_process_time(RID p_particles, float p_time);
+ void particles_set_pre_process_time(RID p_particles, double p_time);
void particles_set_explosiveness_ratio(RID p_particles, float p_ratio);
void particles_set_randomness_ratio(RID p_particles, float p_ratio);
void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
- void particles_set_speed_scale(RID p_particles, float p_scale);
+ void particles_set_speed_scale(RID p_particles, double p_scale);
void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
void particles_set_process_material(RID p_particles, RID p_material);
void particles_set_fixed_fps(RID p_particles, int p_fps);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index b3a349c948..4f140dd10d 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -466,6 +466,11 @@ layout(location = 0) out vec4 frag_color;
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+/* Make a default specular mode SPECULAR_SCHLICK_GGX. */
+#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON)
+#define SPECULAR_SCHLICK_GGX
+#endif
+
#include "scene_forward_lights_inc.glsl"
#include "scene_forward_gi_inc.glsl"
@@ -907,6 +912,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
+ specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 70900a847c..681656e1d5 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -491,6 +491,11 @@ layout(location = 0) out vec4 frag_color;
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
+/* Make a default specular mode SPECULAR_SCHLICK_GGX. */
+#if !defined(SPECULAR_DISABLED) && !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) && !defined(SPECULAR_PHONG) && !defined(SPECULAR_TOON)
+#define SPECULAR_SCHLICK_GGX
+#endif
+
#include "scene_forward_lights_inc.glsl"
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -843,6 +848,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
+ specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
diff --git a/servers/rendering/renderer_rd/shaders/tonemap.glsl b/servers/rendering/renderer_rd/shaders/tonemap.glsl
index f028195a74..3c685c25b9 100644
--- a/servers/rendering/renderer_rd/shaders/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/tonemap.glsl
@@ -184,10 +184,6 @@ vec3 tonemap_aces(vec3 color, float white) {
}
vec3 tonemap_reinhard(vec3 color, float white) {
- // Ensure color values are positive.
- // They can be negative in the case of negative lights, which leads to undesired behavior.
- color = max(vec3(0.0), color);
-
return (white * color + color) / (color * white + white);
}
@@ -211,7 +207,7 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
return tonemap_reinhard(color, white);
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
return tonemap_filmic(color, white);
- } else { //aces
+ } else { // TONEMAPPER_ACES
return tonemap_aces(color, white);
}
}
@@ -405,7 +401,9 @@ void main() {
color += screen_space_dither(gl_FragCoord.xy);
}
- color = apply_tonemapping(color, params.white);
+ // Ensure color values passed to tonemappers are positive.
+ // They can be negative in the case of negative lights, which leads to undesired behavior.
+ color = apply_tonemapping(max(vec3(0.0), color), params.white);
color = linear_to_srgb(color); // regular linear -> SRGB conversion
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 83d1b33bf2..6357a6f4c2 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1866,7 +1866,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
//rotate it
Basis rot = lightmap->transform.basis.orthonormalized();
for (int i = 0; i < 3; i++) {
- float csh[9];
+ real_t csh[9];
for (int j = 0; j < 9; j++) {
csh[j] = sh[j][i];
}
@@ -1878,7 +1878,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 inner_pos = ((lm_pos - bounds.position) / bounds.size) * 2.0 - Vector3(1.0, 1.0, 1.0);
- float blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
+ real_t blend = MAX(inner_pos.x, MAX(inner_pos.y, inner_pos.z));
//make blend more rounded
blend = Math::lerp(inner_pos.length(), blend, blend);
blend *= blend;
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 1d0f53c0bf..e06b3ba153 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const float p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, float p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index b9bc349f79..6ffbdbf685 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -468,13 +468,13 @@ public:
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
- virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
- virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
- virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 0297724a22..bb9ffffe8a 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -420,8 +420,8 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color()));
- ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
- ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
@@ -431,7 +431,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_draw", "draw_list", "use_indices", "instances", "procedural_vertex_count"), &RenderingDevice::draw_list_draw, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("draw_list_enable_scissor", "draw_list", "rect"), &RenderingDevice::draw_list_enable_scissor, DEFVAL(Rect2()));
ClassDB::bind_method(D_METHOD("draw_list_disable_scissor", "draw_list"), &RenderingDevice::draw_list_disable_scissor);
ClassDB::bind_method(D_METHOD("draw_list_switch_to_next_pass"), &RenderingDevice::draw_list_switch_to_next_pass);
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index c79dfb1649..bed6ade1f6 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -134,8 +134,8 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
if (RSG::storage->capturing_timestamps) {
- new_profile.write[i].gpu_msec = float((time_gpu - base_gpu) / 1000) / 1000.0;
- new_profile.write[i].cpu_msec = float(time_cpu - base_cpu) / 1000.0;
+ new_profile.write[i].gpu_msec = double((time_gpu - base_gpu) / 1000) / 1000.0;
+ new_profile.write[i].cpu_msec = double(time_cpu - base_cpu) / 1000.0;
new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
}
}
@@ -149,7 +149,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
if (print_frame_profile_ticks_from == 0) {
print_frame_profile_ticks_from = OS::get_singleton()->get_ticks_usec();
}
- float total_time = 0.0;
+ double total_time = 0.0;
for (int i = 0; i < frame_profile.size() - 1; i++) {
String name = frame_profile[i].name;
@@ -157,7 +157,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
continue;
}
- float time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
+ double time = frame_profile[i + 1].gpu_msec - frame_profile[i].gpu_msec;
if (name[0] != '<' && name[0] != '>') {
if (print_gpu_profile_task_time.has(name)) {
@@ -179,7 +179,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
float print_threshold = 0.01;
for (OrderedHashMap<String, float>::Element E = print_gpu_profile_task_time.front(); E; E = E.next()) {
- float time = E.value() / float(print_frame_profile_frame_count);
+ double time = E.value() / double(print_frame_profile_frame_count);
if (time > print_threshold) {
print_line("\t-" + E.key() + ": " + rtos(time) + "ms");
}
@@ -193,7 +193,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::storage->update_memory_info();
}
-float RenderingServerDefault::get_frame_setup_time_cpu() const {
+double RenderingServerDefault::get_frame_setup_time_cpu() const {
return frame_setup_time;
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 282b0564da..381f38d80e 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -71,7 +71,7 @@ class RenderingServerDefault : public RenderingServer {
uint64_t frame_profile_frame;
Vector<FrameProfileArea> frame_profile;
- float frame_setup_time = 0;
+ double frame_setup_time = 0;
//for printing
bool print_gpu_profile = false;
@@ -440,13 +440,13 @@ public:
FUNC2(particles_set_emitting, RID, bool)
FUNC1R(bool, particles_get_emitting, RID)
FUNC2(particles_set_amount, RID, int)
- FUNC2(particles_set_lifetime, RID, float)
+ FUNC2(particles_set_lifetime, RID, double)
FUNC2(particles_set_one_shot, RID, bool)
- FUNC2(particles_set_pre_process_time, RID, float)
+ FUNC2(particles_set_pre_process_time, RID, double)
FUNC2(particles_set_explosiveness_ratio, RID, float)
FUNC2(particles_set_randomness_ratio, RID, float)
FUNC2(particles_set_custom_aabb, RID, const AABB &)
- FUNC2(particles_set_speed_scale, RID, float)
+ FUNC2(particles_set_speed_scale, RID, double)
FUNC2(particles_set_use_local_coordinates, RID, bool)
FUNC2(particles_set_process_material, RID, RID)
FUNC2(particles_set_fixed_fps, RID, int)
@@ -574,8 +574,8 @@ public:
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
FUNC2(viewport_set_measure_render_time, RID, bool)
- FUNC1RC(float, viewport_get_measured_render_time_cpu, RID)
- FUNC1RC(float, viewport_get_measured_render_time_gpu, RID)
+ FUNC1RC(double, viewport_get_measured_render_time_cpu, RID)
+ FUNC1RC(double, viewport_get_measured_render_time_gpu, RID)
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
@@ -890,7 +890,7 @@ public:
/* TESTING */
- virtual float get_frame_setup_time_cpu() const override;
+ virtual double get_frame_setup_time_cpu() const override;
virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) override;
virtual void set_default_clear_color(const Color &p_color) override;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 314b59869d..2da8e0f297 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -242,7 +242,7 @@ RID RenderingServer::_make_test_cube() {
return test_cube;
}
-RID RenderingServer::make_sphere_mesh(int p_lats, int p_lons, float p_radius) {
+RID RenderingServer::make_sphere_mesh(int p_lats, int p_lons, real_t p_radius) {
Vector<Vector3> vertices;
Vector<Vector3> normals;
const double lat_step = Math_TAU / p_lats;
@@ -412,26 +412,40 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
} break;
case RS::ARRAY_TANGENT: {
- ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
+ Variant::Type type = p_arrays[ai].get_type();
+ ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
+ if (type == Variant::PACKED_FLOAT32_ARRAY) {
+ Vector<float> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
+ const float *src = array.ptr();
- Vector<real_t> array = p_arrays[ai];
-
- ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
-
- const real_t *src = array.ptr();
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ uint32_t value = 0;
+ value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (src[i * 4 + 3] > 0) {
+ value |= 3 << 30;
+ }
- for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- if (src[i * 4 + 3] > 0) {
- value |= 3 << 30;
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
}
+ } else { // if (type == Variant::PACKED_FLOAT64_ARRAY)
+ Vector<double> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
+ const double *src = array.ptr();
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ uint32_t value = 0;
+ value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
+ value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
+ value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
+ if (src[i * 4 + 3] > 0) {
+ value |= 3 << 30;
+ }
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ }
}
-
} break;
case RS::ARRAY_COLOR: {
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_COLOR_ARRAY, ERR_INVALID_PARAMETER);
@@ -543,27 +557,38 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
} break;
case RS::ARRAY_WEIGHTS: {
- ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
-
+ Variant::Type type = p_arrays[ai].get_type();
+ ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
uint32_t bone_count = (p_format & ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 8 : 4;
+ if (type == Variant::PACKED_FLOAT32_ARRAY) {
+ Vector<float> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
+ const float *src = array.ptr();
+ {
+ uint16_t data[8];
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ for (uint32_t j = 0; j < bone_count; j++) {
+ data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ }
- Vector<real_t> array = p_arrays[ai];
-
- ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
-
- const real_t *src = array.ptr();
-
- {
- uint16_t data[8];
- for (int i = 0; i < p_vertex_array_len; i++) {
- for (uint32_t j = 0; j < bone_count; j++) {
- data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
}
+ }
+ } else { // if (type == Variant::PACKED_FLOAT64_ARRAY)
+ Vector<double> array = p_arrays[ai];
+ ERR_FAIL_COND_V(array.size() != (int32_t)(p_vertex_array_len * bone_count), ERR_INVALID_PARAMETER);
+ const double *src = array.ptr();
+ {
+ uint16_t data[8];
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ for (uint32_t j = 0; j < bone_count; j++) {
+ data[j] = CLAMP(src[i * bone_count + j] * 65535, 0, 65535);
+ }
- memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
+ memcpy(&sw[p_offsets[ai] + i * p_skin_stride], data, 2 * bone_count);
+ }
}
}
-
} break;
case RS::ARRAY_BONES: {
ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 28aee1b575..6b789a6121 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -613,13 +613,13 @@ public:
virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
- virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
- virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
- virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
@@ -900,8 +900,8 @@ public:
virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0;
virtual void viewport_set_measure_render_time(RID p_viewport, bool p_enable) = 0;
- virtual float viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
- virtual float viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
+ virtual double viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
+ virtual double viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
/* SKY API */
@@ -1436,15 +1436,15 @@ public:
struct FrameProfileArea {
String name;
- float gpu_msec;
- float cpu_msec;
+ double gpu_msec;
+ double cpu_msec;
};
virtual void set_frame_profiling_enabled(bool p_enable) = 0;
virtual Vector<FrameProfileArea> get_frame_profile() = 0;
virtual uint64_t get_frame_profile_frame() = 0;
- virtual float get_frame_setup_time_cpu() const = 0;
+ virtual double get_frame_setup_time_cpu() const = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
@@ -1457,7 +1457,7 @@ public:
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
- virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius);
+ virtual RID make_sphere_mesh(int p_lats, int p_lons, real_t p_radius);
virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data);
virtual void mesh_add_surface_from_planes(RID p_mesh, const Vector<Plane> &p_planes);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 1491368109..e32ea9cdea 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -314,8 +314,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""));
- ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(VALIGN_CENTER), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(VALIGN_CENTER));
+ ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGN_CENTER), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("shaped_text_substr", "shaped", "start", "length"), &TextServer::shaped_text_substr);
ClassDB::bind_method(D_METHOD("shaped_text_get_parent", "shaped"), &TextServer::shaped_text_get_parent);
diff --git a/servers/text_server.h b/servers/text_server.h
index 4c2ada7fc9..d824504bf4 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -181,7 +181,7 @@ public:
struct EmbeddedObject {
int pos = 0;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_CENTER;
Rect2 rect;
};
Map<Variant, EmbeddedObject> objects;
@@ -332,8 +332,8 @@ public:
virtual bool shaped_text_get_preserve_control(RID p_shaped) const = 0;
virtual bool shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "") = 0;
- virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER, int p_length = 1) = 0;
- virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, VAlign p_inline_align = VALIGN_CENTER) = 0;
+ virtual bool shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER, int p_length = 1) = 0;
+ virtual bool shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align = INLINE_ALIGN_CENTER) = 0;
virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(RID p_shaped) const = 0;
diff --git a/tests/test_math.cpp b/tests/test_math.cpp
index d0b9fdef4b..a44040dfe2 100644
--- a/tests/test_math.cpp
+++ b/tests/test_math.cpp
@@ -589,13 +589,13 @@ MainLoop *test() {
{
Vector3 v(1, 2, 3);
v.normalize();
- float a = 0.3;
+ real_t a = 0.3;
Basis m(v, a);
Vector3 v2(7, 3, 1);
v2.normalize();
- float a2 = 0.8;
+ real_t a2 = 0.8;
Basis m2(v2, a2);
diff --git a/tests/test_render.cpp b/tests/test_render.cpp
index beff86dd83..21b4da9b3b 100644
--- a/tests/test_render.cpp
+++ b/tests/test_render.cpp
@@ -184,7 +184,7 @@ public:
light = vs->instance_create2(lightaux, scenario);
Transform3D lla;
//lla.set_look_at(Vector3(),Vector3(1, -1, 1));
- lla.set_look_at(Vector3(), Vector3(0.0, -0.836026, -0.548690));
+ lla.basis = Basis::looking_at(Vector3(0.0, -0.836026, -0.548690));
vs->instance_set_transform(light, lla);