diff options
41 files changed, 282 insertions, 147 deletions
diff --git a/.travis.yml b/.travis.yml index 9376fbcc06..2639cf9661 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,15 +100,15 @@ matrix: packages: - *linux_deps -# - name: Javascript export template (release, emscripten latest) -# stage: build -# env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes" -# os: linux -# compiler: clang -# addons: -# apt: -# packages: -# - *linux_deps + - name: JavaScript export template (release, emscripten latest) + stage: build + env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes" + os: linux + compiler: clang + addons: + apt: + packages: + - *linux_deps before_install: - eval "${MATRIX_EVAL}" diff --git a/core/image.cpp b/core/image.cpp index 45f10625a9..e2b184fcde 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -30,6 +30,7 @@ #include "image.h" +#include "core/error_macros.h" #include "core/hash_map.h" #include "core/io/image_loader.h" #include "core/io/resource_loader.h" @@ -2629,6 +2630,7 @@ void Image::fill(const Color &c) { ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr; void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr; @@ -3058,6 +3060,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer); ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer); ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer); + ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); @@ -3389,6 +3392,11 @@ Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) { return _load_from_buffer(p_array, _webp_mem_loader_func); } +Error Image::load_tga_from_buffer(const Vector<uint8_t> &p_array) { + ERR_FAIL_NULL_V_MSG(_tga_mem_loader_func, ERR_UNAVAILABLE, "TGA module was not installed."); + return _load_from_buffer(p_array, _tga_mem_loader_func); +} + void Image::convert_rg_to_ra_rgba8() { ERR_FAIL_COND(format != FORMAT_RGBA8); ERR_FAIL_COND(!data.size()); diff --git a/core/image.h b/core/image.h index 53c203998e..711bf5721c 100644 --- a/core/image.h +++ b/core/image.h @@ -135,6 +135,7 @@ public: static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; + static ImageMemLoadFunc _tga_mem_loader_func; static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); @@ -360,6 +361,7 @@ public: Error load_png_from_buffer(const Vector<uint8_t> &p_array); Error load_jpg_from_buffer(const Vector<uint8_t> &p_array); Error load_webp_from_buffer(const Vector<uint8_t> &p_array); + Error load_tga_from_buffer(const Vector<uint8_t> &p_array); void convert_rg_to_ra_rgba8(); void convert_ra_rgba8_to_rg(); diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index dc68c2a9f9..434f6fa300 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -48,8 +48,10 @@ void MainLoop::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_ABOUT); BIND_CONSTANT(NOTIFICATION_CRASH); BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE); - BIND_CONSTANT(NOTIFICATION_APP_RESUMED); - BIND_CONSTANT(NOTIFICATION_APP_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_RESUMED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT); ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted"))); }; diff --git a/core/os/main_loop.h b/core/os/main_loop.h index 90790a45a1..2c34cf193c 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -52,8 +52,10 @@ public: NOTIFICATION_WM_ABOUT = 2011, NOTIFICATION_CRASH = 2012, NOTIFICATION_OS_IME_UPDATE = 2013, - NOTIFICATION_APP_RESUMED = 2014, - NOTIFICATION_APP_PAUSED = 2015, + NOTIFICATION_APPLICATION_RESUMED = 2014, + NOTIFICATION_APPLICATION_PAUSED = 2015, + NOTIFICATION_APPLICATION_FOCUS_IN = 2016, + NOTIFICATION_APPLICATION_FOCUS_OUT = 2017, }; virtual void init(); diff --git a/core/os/os.cpp b/core/os/os.cpp index c842be333c..231069fcfb 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -41,6 +41,7 @@ #include <stdarg.h> OS *OS::singleton = nullptr; +uint64_t OS::target_ticks = 0; OS *OS::get_singleton() { return singleton; @@ -468,6 +469,41 @@ void OS::close_midi_inputs() { } } +void OS::add_frame_delay(bool p_can_draw) { + const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); + if (frame_delay) { + // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take + // the actual frame time into account. + // Due to the high fluctuation of the actual sleep duration, it's not recommended + // to use this as a FPS limiter. + delay_usec(frame_delay * 1000); + } + + // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the + // previous frame time into account for a smoother result. + uint64_t dynamic_delay = 0; + if (is_in_low_processor_usage_mode() || !p_can_draw) { + dynamic_delay = get_low_processor_usage_mode_sleep_usec(); + } + const int target_fps = Engine::get_singleton()->get_target_fps(); + if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) { + // Override the low processor usage mode sleep delay if the target FPS is lower. + dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps)); + } + + if (dynamic_delay > 0) { + target_ticks += dynamic_delay; + uint64_t current_ticks = get_ticks_usec(); + + if (current_ticks < target_ticks) { + delay_usec(target_ticks - current_ticks); + } + + current_ticks = get_ticks_usec(); + target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay); + } +} + OS::OS() { void *volatile stack_bottom; diff --git a/core/os/os.h b/core/os/os.h index 04e10518dc..f21c0d4df7 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -43,6 +43,7 @@ class OS { static OS *singleton; + static uint64_t target_ticks; String _execpath; List<String> _cmdline; bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. @@ -212,6 +213,8 @@ public: virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const = 0; + virtual void add_frame_delay(bool p_can_draw); + virtual uint64_t get_ticks_usec() const = 0; uint32_t get_ticks_msec() const; uint64_t get_splash_tick_msec() const; diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml index 9a162dabbb..63e13954ab 100644 --- a/doc/classes/PhysicsShapeQueryParameters2D.xml +++ b/doc/classes/PhysicsShapeQueryParameters2D.xml @@ -9,15 +9,6 @@ <tutorials> </tutorials> <methods> - <method name="set_shape"> - <return type="void"> - </return> - <argument index="0" name="shape" type="Resource"> - </argument> - <description> - Sets the [Shape2D] that will be used for collision/intersection queries. - </description> - </method> </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> @@ -38,8 +29,24 @@ <member name="motion" type="Vector2" setter="set_motion" getter="get_motion" default="Vector2( 0, 0 )"> The motion of the shape being queried for. </member> + <member name="shape" type="Resource" setter="set_shape" getter="get_shape"> + The [Shape2D] that will be used for collision/intersection queries. This stores the actual reference which avoids the shape to be released while being used for queries, so always prefer using this over [member shape_rid]. + </member> <member name="shape_rid" type="RID" setter="set_shape_rid" getter="get_shape_rid"> - The queried shape's [RID]. See also [method set_shape]. + The queried shape's [RID] that will be used for collision/intersection queries. Use this over [member shape] if you want to optimize for performance using the Servers API: + [codeblock] + var shape_rid = PhysicsServer2D.circle_shape_create() + var radius = 64 + PhysicsServer2D.shape_set_data(shape_rid, radius) + + var params = PhysicsShapeQueryParameters2D.new() + params.shape_rid = shape_rid + + # Execute physics queries here... + + # Release the shape when done with physics queries. + PhysicsServer2D.free_rid(shape_rid) + [/codeblock] </member> <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D( 1, 0, 0, 1, 0, 0 )"> The queried shape's transform matrix. diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml index 6606cfbc59..f4191d4862 100644 --- a/doc/classes/PhysicsShapeQueryParameters3D.xml +++ b/doc/classes/PhysicsShapeQueryParameters3D.xml @@ -9,15 +9,6 @@ <tutorials> </tutorials> <methods> - <method name="set_shape"> - <return type="void"> - </return> - <argument index="0" name="shape" type="Resource"> - </argument> - <description> - Sets the [Shape3D] that will be used for collision/intersection queries. - </description> - </method> </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> @@ -35,8 +26,24 @@ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0"> The collision margin for the shape. </member> + <member name="shape" type="Resource" setter="set_shape" getter="get_shape"> + The [Shape3D] that will be used for collision/intersection queries. This stores the actual reference which avoids the shape to be released while being used for queries, so always prefer using this over [member shape_rid]. + </member> <member name="shape_rid" type="RID" setter="set_shape_rid" getter="get_shape_rid"> - The queried shape's [RID]. See also [method set_shape]. + The queried shape's [RID] that will be used for collision/intersection queries. Use this over [member shape] if you want to optimize for performance using the Servers API: + [codeblock] + var shape_rid = PhysicsServer3D.shape_create(PhysicsServer3D.SHAPE_SPHERE) + var radius = 2.0 + PhysicsServer3D.shape_set_data(shape_rid, radius) + + var params = PhysicsShapeQueryParameters3D.new() + params.shape_rid = shape_rid + + # Execute physics queries here... + + # Release the shape when done with physics queries. + PhysicsServer3D.free_rid(shape_rid) + [/codeblock] </member> <member name="transform" type="Transform" setter="set_transform" getter="get_transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )"> The queried shape's transform matrix. diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 7af7678f63..636a885c89 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -51,6 +51,14 @@ public: int get_directional_light_shadow_size(RID p_light_intance) { return 0; } void set_directional_shadow_count(int p_count) {} + /* SDFGI UPDATE */ + + virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {} + virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const { return 0; } + virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { return AABB(); } + virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { return 0; } + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {} + /* SKY API */ RID sky_create() { return RID(); } @@ -87,6 +95,11 @@ public: virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {} virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) {} + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, bool p_enhance_ssr, float p_energy, float p_normal_bias, float p_probe_bias) {} + + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) {} + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) {} + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {} void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} @@ -114,6 +127,7 @@ public: RID light_instance_create(RID p_light) { return RID(); } void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {} + virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {} void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) {} void light_instance_mark_visible(RID p_light_instance) {} @@ -137,9 +151,13 @@ public: virtual bool gi_probe_needs_update(RID p_probe) const { return false; } virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) {} + virtual void gi_probe_set_quality(RS::GIProbeQuality) {} + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {} void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {} virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {} + virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) {} + virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) {} void set_scene_pass(uint64_t p_pass) {} virtual void set_time(double p_time, double p_step) {} @@ -148,7 +166,7 @@ public: virtual RID render_buffers_create() { return RID(); } virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) {} - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) {} + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) {} virtual bool screen_space_roughness_limiter_is_active() const { return false; } virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {} @@ -158,6 +176,7 @@ public: bool free(RID p_rid) { return true; } virtual void update() {} + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {} RasterizerSceneDummy() {} ~RasterizerSceneDummy() {} @@ -576,7 +595,8 @@ public: void light_set_negative(RID p_light, bool p_enable) {} void light_set_cull_mask(RID p_light, uint32_t p_mask) {} void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {} - void light_set_use_gi(RID p_light, bool p_enabled) {} + void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {} + void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {} void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {} @@ -595,7 +615,8 @@ public: AABB light_get_aabb(RID p_light) const { return AABB(); } float light_get_param(RID p_light, RS::LightParam p_param) { return 0.0; } Color light_get_color(RID p_light) { return Color(); } - bool light_get_use_gi(RID p_light) { return false; } + virtual RS::LightBakeMode light_get_bake_mode(RID p_light) { return RS::LIGHT_BAKE_DISABLED; } + virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) { return 0; } uint64_t light_get_version(RID p_light) const { return 0; } /* PROBE API */ @@ -604,9 +625,9 @@ public: void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {} void reflection_probe_set_intensity(RID p_probe, float p_intensity) {} - void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {} - void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {} - void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {} + void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {} + void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {} + void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {} void reflection_probe_set_max_distance(RID p_probe, float p_distance) {} void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {} void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {} diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index d2b9405552..4392538737 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -332,17 +332,10 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { if (search_flags & SEARCH_METHODS) { for (int i = 0; i < class_doc.methods.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); - String aux_term = (search_flags & SEARCH_CASE_SENSITIVE) ? term : term.to_lower(); - - if (aux_term.begins_with(".")) { - aux_term = aux_term.right(1); - } - - if (aux_term.ends_with("(")) { - aux_term = aux_term.left(aux_term.length() - 1).strip_edges(); - } - - if (aux_term.is_subsequence_of(method_name)) { + if (method_name.find(term) > -1 || + (term.begins_with(".") && method_name.begins_with(term.right(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i])); } } @@ -448,9 +441,9 @@ bool EditorHelpSearch::Runner::_phase_select_match() { bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const { if (search_flags & SEARCH_CASE_SENSITIVE) { - return p_term.is_subsequence_of(p_string); + return p_string.find(p_term) > -1; } else { - return p_term.is_subsequence_ofi(p_string); + return p_string.findn(p_term) > -1; } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index f2f8805aaf..8909fb2cfe 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -435,14 +435,14 @@ void EditorNode::_notification(int p_what) { /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_APPLICATION_FOCUS_IN: { // Restore the original FPS cap after focusing back on the editor OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec"))); EditorFileSystem::get_singleton()->scan_changes(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_APPLICATION_FOCUS_OUT: { // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec"))); } break; diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index b5f1133a9e..fe49198e8f 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -39,7 +39,7 @@ #include "scene/gui/margin_container.h" void EditorPluginSettings::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { update_plugins(); } else if (p_what == Node::NOTIFICATION_READY) { plugin_config_dialog->connect_compat("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 67d92c4839..d76a3d2da7 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -182,8 +182,8 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { } void EditorSpinSlider::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_OUT || - p_what == NOTIFICATION_WM_FOCUS_IN || + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT || + p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN || p_what == NOTIFICATION_EXIT_TREE) { if (grabbing_spinner) { grabber->hide(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 96079d5418..fd415d40da 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1337,7 +1337,7 @@ void ScriptEditor::_notification(int p_what) { editor->disconnect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop)); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { _test_script_times_on_disk(); _update_modified_scripts_for_external_editor(); } break; diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 0c3a44e4cd..7dd0b8a238 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -338,7 +338,7 @@ void ShaderEditor::_menu_option(int p_option) { } void ShaderEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { _check_for_external_edit(); } } diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 0ac29f68f6..f15a801530 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -200,7 +200,7 @@ void ShaderFileEditor::_update_options() { } void ShaderFileEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { if (is_visible_in_tree() && shader_file.is_valid()) { _update_options(); } diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 3a92818779..762f42abeb 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -780,7 +780,7 @@ void TextureRegionEditor::_notification(int p_what) { _update_autoslice(); } } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { // This happens when the user leaves the Editor and returns, // they could have changed the textures, so the cache is cleared. cache_map.clear(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index dd42ed9760..04ac809d03 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -350,17 +350,22 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!profile_allow_editing) { break; } - String preferred = ""; - Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); + // Prefer nodes that inherit from the current scene root. + Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); if (current_edited_scene_root) { - if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node2D")) { - preferred = "Node2D"; - } else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node3D")) { - preferred = "Node3D"; + static const String preferred_types[] = { "Node2D", "Node3D", "Control" }; + + StringName root_class = current_edited_scene_root->get_class_name(); + + for (int i = 0; i < preferred_types->size(); i++) { + if (ClassDB::is_parent_class(root_class, preferred_types[i])) { + create_dialog->set_preferred_search_result_type(preferred_types[i]); + break; + } } } - create_dialog->set_preferred_search_result_type(preferred); + create_dialog->popup_create(true); } break; case TOOL_INSTANCE: { diff --git a/main/main.cpp b/main/main.cpp index 00760b39b0..0cccccdab3 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2115,7 +2115,6 @@ bool Main::start() { */ uint64_t Main::last_ticks = 0; -uint64_t Main::target_ticks = 0; uint32_t Main::frames = 0; uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; @@ -2266,38 +2265,7 @@ bool Main::iteration() { return exit; } - const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); - if (frame_delay) { - // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take - // the actual frame time into account. - // Due to the high fluctuation of the actual sleep duration, it's not recommended - // to use this as a FPS limiter. - OS::get_singleton()->delay_usec(frame_delay * 1000); - } - - // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the - // previous frame time into account for a smoother result. - uint64_t dynamic_delay = 0; - if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->window_can_draw()) { - dynamic_delay = OS::get_singleton()->get_low_processor_usage_mode_sleep_usec(); - } - const int target_fps = Engine::get_singleton()->get_target_fps(); - if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) { - // Override the low processor usage mode sleep delay if the target FPS is lower. - dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps)); - } - - if (dynamic_delay > 0) { - target_ticks += dynamic_delay; - uint64_t current_ticks = OS::get_singleton()->get_ticks_usec(); - - if (current_ticks < target_ticks) { - OS::get_singleton()->delay_usec(target_ticks - current_ticks); - } - - current_ticks = OS::get_singleton()->get_ticks_usec(); - target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay); - } + OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw()); #ifdef TOOLS_ENABLED if (auto_build_solutions) { diff --git a/main/main.h b/main/main.h index ab6917a65c..308128735c 100644 --- a/main/main.h +++ b/main/main.h @@ -38,7 +38,6 @@ class Main { static void print_help(const char *p_binary); static uint64_t last_ticks; - static uint64_t target_ticks; static uint32_t frames; static uint32_t frame; static bool force_redraw_requested; diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index d0c9bf5d38..6c0a3a4ca3 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -523,7 +523,7 @@ void CSGBrushOperation::MeshMerge::_add_distance(List<real_t> &r_intersectionsA, // Check if distance exists. for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) { - if (Math::abs(**E - p_distance) < vertex_snap) { + if (Math::is_equal_approx(**E, p_distance)) { return; } } @@ -1068,15 +1068,6 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s break; } - // Don't create degenerate triangles. - Vector2 split_edge1[2] = { vertices[new_vertex_idx].point, edge_points[0] }; - Vector2 split_edge2[2] = { vertices[new_vertex_idx].point, edge_points[1] }; - Vector2 new_edge[2] = { vertices[new_vertex_idx].point, vertices[opposite_vertex_idx].point }; - if (are_segements_parallel(split_edge1, new_edge, vertex_snap2) && - are_segements_parallel(split_edge2, new_edge, vertex_snap2)) { - break; - } - // If opposite point is on the segemnt, add its index to segment indices too. Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points); if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) { diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 06b9534fce..94aa2125c2 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1853,7 +1853,7 @@ void NativeReloadNode::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_APPLICATION_FOCUS_OUT: { if (unloaded) { break; } @@ -1887,7 +1887,7 @@ void NativeReloadNode::_notification(int p_what) { } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_APPLICATION_FOCUS_IN: { if (!unloaded) { break; } diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index ce889a4928..1475d24792 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -30,6 +30,8 @@ #include "image_loader_tga.h" +#include "core/error_macros.h" +#include "core/io/file_access_memory.h" #include "core/os/os.h" #include "core/print_string.h" @@ -311,5 +313,17 @@ void ImageLoaderTGA::get_recognized_extensions(List<String> *p_extensions) const p_extensions->push_back("tga"); } +static Ref<Image> _tga_mem_loader_func(const uint8_t *p_png, int p_size) { + FileAccessMemory memfile; + Error open_memfile_error = memfile.open_custom(p_png, p_size); + ERR_FAIL_COND_V_MSG(open_memfile_error, Ref<Image>(), "Could not create memfile for TGA image buffer."); + Ref<Image> img; + img.instance(); + Error load_error = ImageLoaderTGA().load_image(img, &memfile, false, 1.0f); + ERR_FAIL_COND_V_MSG(load_error, Ref<Image>(), "Failed to load TGA image."); + return img; +} + ImageLoaderTGA::ImageLoaderTGA() { + Image::_tga_mem_loader_func = _tga_mem_loader_func; } diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index a032ae8d2c..4610b94363 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -457,7 +457,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI return; if (os_android->get_main_loop()) { - os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_RESUMED); + os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED); } } @@ -466,7 +466,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIE return; if (os_android->get_main_loop()) { - os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_PAUSED); + os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED); } } } diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 920fd24c4a..93f6e3540a 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -197,6 +197,18 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { } } +- (void)applicationDidResignActive:(NSNotification *)notification { + if (OS_OSX::get_singleton()->get_main_loop()) { + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + if (OS_OSX::get_singleton()->get_main_loop()) { + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } +} + - (void)globalMenuCallback:(id)sender { if (![sender representedObject]) return; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index f47afcc4e5..61dc156fbc 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -1790,6 +1790,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA // Restore mouse mode _set_mouse_mode_impl(mouse_mode); + if (!app_focused) { + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } + app_focused = true; + } break; } case WM_KILLFOCUS: { @@ -1805,6 +1811,19 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } touch_state.clear(); + bool self_steal = false; + HWND new_hwnd = (HWND)wParam; + if (IsWindow(new_hwnd)) { + self_steal = true; + } + + if (!self_steal) { + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } + app_focused = false; + } + break; } case WM_ACTIVATE: // Watch For Window Activate Message diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 995ced0809..8433bb449b 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -317,6 +317,7 @@ private: int pressrc; HINSTANCE hInstance; // Holds The Instance Of The Application String rendering_driver; + bool app_focused = false; struct WindowData { HWND hWnd; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index c6897fc684..bacc65c7bf 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -51,7 +51,9 @@ void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) { } void AcceptDialog::_parent_focused() { - _cancel_pressed(); + if (!is_exclusive()) { + _cancel_pressed(); + } } void AcceptDialog::_notification(int p_what) { @@ -295,6 +297,7 @@ AcceptDialog::AcceptDialog() { set_wrap_controls(true); set_visible(false); set_transient(true); + set_exclusive(true); bg = memnew(Panel); add_child(bg); diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index 5d7b6272bf..81664733a3 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -44,6 +44,7 @@ class LineEdit; class AcceptDialog : public Window { GDCLASS(AcceptDialog, Window); +public: Window *parent_visible; Panel *bg; HBoxContainer *hbc; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ba55927980..251f31ce4e 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -688,12 +688,12 @@ void LineEdit::_notification(int p_what) { update_placeholder_width(); update(); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index c7fc8dbe43..3860ce61e9 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -603,12 +603,12 @@ void TextEdit::_notification(int p_what) { _update_wrap_at(); syntax_highlighting_cache.clear(); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 1bf828a03b..88f9730f78 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2857,8 +2857,8 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); + BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_OUT); BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED); @@ -2867,8 +2867,10 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_ABOUT); BIND_CONSTANT(NOTIFICATION_CRASH); BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE); - BIND_CONSTANT(NOTIFICATION_APP_RESUMED); - BIND_CONSTANT(NOTIFICATION_APP_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_RESUMED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT); BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT); BIND_ENUM_CONSTANT(PAUSE_MODE_STOP); diff --git a/scene/main/node.h b/scene/main/node.h index 7595aabd9a..c3972e2d8e 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -243,8 +243,8 @@ public: NOTIFICATION_WM_MOUSE_ENTER = 1002, NOTIFICATION_WM_MOUSE_EXIT = 1003, - NOTIFICATION_WM_FOCUS_IN = 1004, - NOTIFICATION_WM_FOCUS_OUT = 1005, + NOTIFICATION_WM_WINDOW_FOCUS_IN = 1004, + NOTIFICATION_WM_WINDOW_FOCUS_OUT = 1005, NOTIFICATION_WM_CLOSE_REQUEST = 1006, NOTIFICATION_WM_GO_BACK_REQUEST = 1007, NOTIFICATION_WM_SIZE_CHANGED = 1008, @@ -255,8 +255,10 @@ public: NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT, NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH, NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE, - NOTIFICATION_APP_RESUMED = MainLoop::NOTIFICATION_APP_RESUMED, - NOTIFICATION_APP_PAUSED = MainLoop::NOTIFICATION_APP_PAUSED + NOTIFICATION_APPLICATION_RESUMED = MainLoop::NOTIFICATION_APPLICATION_RESUMED, + NOTIFICATION_APPLICATION_PAUSED = MainLoop::NOTIFICATION_APPLICATION_PAUSED, + NOTIFICATION_APPLICATION_FOCUS_IN = MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN, + NOTIFICATION_APPLICATION_FOCUS_OUT = MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT }; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 3c3c7533a3..a418883506 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -587,9 +587,11 @@ void SceneTree::_notification(int p_notification) { case NOTIFICATION_OS_IME_UPDATE: case NOTIFICATION_WM_ABOUT: case NOTIFICATION_CRASH: - case NOTIFICATION_APP_RESUMED: - case NOTIFICATION_APP_PAUSED: { - get_root()->propagate_notification(p_notification); + case NOTIFICATION_APPLICATION_RESUMED: + case NOTIFICATION_APPLICATION_PAUSED: + case NOTIFICATION_APPLICATION_FOCUS_IN: + case NOTIFICATION_APPLICATION_FOCUS_OUT: { + get_root()->propagate_notification(p_notification); //pass these to nodes, since they are mirrored } break; default: diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 606f39370b..8042f02fa6 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -815,7 +815,7 @@ void Viewport::_notification(int p_what) { } break; case NOTIFICATION_WM_MOUSE_EXIT: - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { _drop_physics_mouseover(); if (gui.mouse_focus && !gui.forced_mouse_focus) { diff --git a/scene/main/window.cpp b/scene/main/window.cpp index a9be8a1eff..7f2160c6a5 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -316,13 +316,13 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { } break; case DisplayServer::WINDOW_EVENT_FOCUS_IN: { focused = true; - _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN); + _propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_IN); emit_signal("focus_entered"); } break; case DisplayServer::WINDOW_EVENT_FOCUS_OUT: { focused = false; - _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT); + _propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_OUT); emit_signal("focus_exited"); } break; case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: { @@ -398,6 +398,18 @@ void Window::set_visible(bool p_visible) { emit_signal(SceneStringNames::get_singleton()->visibility_changed); RS::get_singleton()->viewport_set_active(get_viewport_rid(), visible); + + //update transient exclusive + if (transient_parent) { + if (exclusive && visible) { + ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); + transient_parent->exclusive_child = this; + } else { + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + } + } } void Window::_clear_transient() { diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 080b8c61ad..19b575a259 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -132,13 +132,21 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape) { - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); +void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + shape = p_shape_ref->get_rid(); +} + +RES PhysicsShapeQueryParameters2D::get_shape() const { + return shape_ref; } void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { - shape = p_shape; + if (shape != p_shape) { + shape_ref = RES(); + shape = p_shape; + } } RID PhysicsShapeQueryParameters2D::get_shape_rid() const { @@ -212,6 +220,7 @@ bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const { void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters2D::get_shape); ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid); @@ -240,7 +249,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 549a78aa1f..b2f2e786ee 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -98,6 +98,8 @@ class PhysicsShapeQueryResult2D; class PhysicsShapeQueryParameters2D : public Reference { GDCLASS(PhysicsShapeQueryParameters2D, Reference); friend class PhysicsDirectSpaceState2D; + + RES shape_ref; RID shape; Transform2D transform; Vector2 motion; @@ -112,7 +114,8 @@ protected: static void _bind_methods(); public: - void set_shape(const RES &p_shape); + void set_shape(const RES &p_shape_ref); + RES get_shape() const; void set_shape_rid(const RID &p_shape); RID get_shape_rid() const; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 9668358710..3b361fee55 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -136,13 +136,21 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape) { - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); +void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + shape = p_shape_ref->get_rid(); +} + +RES PhysicsShapeQueryParameters3D::get_shape() const { + return shape_ref; } void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { - shape = p_shape; + if (shape != p_shape) { + shape_ref = RES(); + shape = p_shape; + } } RID PhysicsShapeQueryParameters3D::get_shape_rid() const { @@ -208,6 +216,7 @@ bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const { void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters3D::get_shape); ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid); @@ -232,7 +241,7 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 2465b40d3e..1cfa4d8565 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -100,6 +100,7 @@ class PhysicsShapeQueryParameters3D : public Reference { GDCLASS(PhysicsShapeQueryParameters3D, Reference); friend class PhysicsDirectSpaceState3D; + RES shape_ref; RID shape; Transform transform; float margin; @@ -113,7 +114,8 @@ protected: static void _bind_methods(); public: - void set_shape(const RES &p_shape); + void set_shape(const RES &p_shape_ref); + RES get_shape() const; void set_shape_rid(const RID &p_shape); RID get_shape_rid() const; |