diff options
47 files changed, 398 insertions, 311 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 1b68f66956..679362d749 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -70,12 +70,12 @@ jobs: run: | ./bin/godot.linuxbsd.opt.tools.64 --test - # Download, unzip and setup SwiftShader library [d4550ab8d3f] + # Download, unzip and setup SwiftShader library [4466040] - name: Download SwiftShader run: | - wget https://github.com/qarmin/gtk_library_store/releases/download/3.24.0/swiftshader.zip - unzip swiftshader.zip - rm swiftshader.zip + wget https://github.com/qarmin/gtk_library_store/releases/download/3.24.0/swiftshader2.zip + unzip swiftshader2.zip + rm swiftshader2.zip curr="$(pwd)/libvk_swiftshader.so" sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json @@ -144,12 +144,10 @@ jobs: scons --version # We should always be explicit with our flags usage here since it's gonna be sure to always set those flags - # [Workaround] SwiftShader doesn't support tessellation, so we skip Godot check about it - name: Compilation env: SCONS_CACHE: ${{github.workspace}}/.scons_cache/ run: | - sed -i "s|ERR_FAIL_COND_V(p_rasterization_state.patch_control_points|//ERR_FAIL_COND_V(p_rasterization_state.patch_control_points|" drivers/vulkan/rendering_device_vulkan.cpp scons tools=yes tests=yes target=debug debug_symbols=no use_asan=yes use_ubsan=yes ls -l bin/ @@ -158,12 +156,12 @@ jobs: run: | ./bin/godot.linuxbsd.tools.64s --test - # Download, unzip and setup SwiftShader library [d4550ab8d3f] + # Download, unzip and setup SwiftShader library [4466040] - name: Download SwiftShader run: | - wget https://github.com/qarmin/gtk_library_store/releases/download/3.24.0/swiftshader.zip - unzip swiftshader.zip - rm swiftshader.zip + wget https://github.com/qarmin/gtk_library_store/releases/download/3.24.0/swiftshader2.zip + unzip swiftshader2.zip + rm swiftshader2.zip curr="$(pwd)/libvk_swiftshader.so" sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 88e11a630c..322eb7ac61 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -35,18 +35,12 @@ #include "scene/scene_string_names.h" int AStar::get_available_point_id() const { - if (points.is_empty()) { - return 1; - } - - // calculate our new next available point id if bigger than before or next id already contained in set of points. if (points.has(last_free_id)) { - int cur_new_id = last_free_id; + int cur_new_id = last_free_id + 1; while (points.has(cur_new_id)) { cur_new_id++; } - int &non_const = const_cast<int &>(last_free_id); - non_const = cur_new_id; + const_cast<int &>(last_free_id) = cur_new_id; } return last_free_id; diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml index b6269520e1..6bb756ea2c 100644 --- a/doc/classes/CollisionObject2D.xml +++ b/doc/classes/CollisionObject2D.xml @@ -200,11 +200,11 @@ <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> The physics layers this CollisionObject2D is in. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. - [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. - [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject2D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml index ecfe758343..0210f6297f 100644 --- a/doc/classes/CollisionObject3D.xml +++ b/doc/classes/CollisionObject3D.xml @@ -171,12 +171,12 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> - The physics layers this CollisionObject3D is in. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. - [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this CollisionObject3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this CollisionObject3D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. - [b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this CollisionObject3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject3D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. diff --git a/doc/classes/SoftBody3D.xml b/doc/classes/SoftBody3D.xml index 16f80c43bc..53bd7e67bf 100644 --- a/doc/classes/SoftBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -68,12 +68,12 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> - The physics layers this SoftBody3D is in. - Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. - A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this SoftBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this SoftBody3D scans for collisions. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. + The physics layers this SoftBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. + [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index d35c519320..a9d0fb6fed 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -577,26 +577,22 @@ Error VulkanContext::_check_capabilities() { multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount; multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex; -#ifdef DEBUG_ENABLED - print_line("- Vulkan multiview supported:"); - print_line(" max view count: " + itos(multiview_capabilities.max_view_count)); - print_line(" max instances: " + itos(multiview_capabilities.max_instance_count)); + print_verbose("- Vulkan multiview supported:"); + print_verbose(" max view count: " + itos(multiview_capabilities.max_view_count)); + print_verbose(" max instances: " + itos(multiview_capabilities.max_instance_count)); } else { - print_line("- Vulkan multiview not supported"); -#endif + print_verbose("- Vulkan multiview not supported"); } -#ifdef DEBUG_ENABLED - print_line("- Vulkan subgroup:"); - print_line(" size: " + itos(subgroup_capabilities.size)); - print_line(" stages: " + subgroup_capabilities.supported_stages_desc()); - print_line(" supported ops: " + subgroup_capabilities.supported_operations_desc()); + print_verbose("- Vulkan subgroup:"); + print_verbose(" size: " + itos(subgroup_capabilities.size)); + print_verbose(" stages: " + subgroup_capabilities.supported_stages_desc()); + print_verbose(" supported ops: " + subgroup_capabilities.supported_operations_desc()); if (subgroup_capabilities.quadOperationsInAllStages) { - print_line(" quad operations in all stages"); + print_verbose(" quad operations in all stages"); } } else { - print_line("- Couldn't call vkGetPhysicalDeviceProperties2"); -#endif + print_verbose("- Couldn't call vkGetPhysicalDeviceProperties2"); } return OK; @@ -737,10 +733,11 @@ Error VulkanContext::_create_physical_device() { } vendor_names[] = { { 0x1002, "AMD" }, { 0x1010, "ImgTec" }, + { 0x106B, "Apple" }, { 0x10DE, "NVIDIA" }, { 0x13B5, "ARM" }, { 0x5143, "Qualcomm" }, - { 0x8086, "INTEL" }, + { 0x8086, "Intel" }, { 0, nullptr }, }; device_name = gpu_props.deviceName; @@ -757,9 +754,9 @@ Error VulkanContext::_create_physical_device() { vendor_idx++; } } -#ifdef DEBUG_ENABLED + print_line("Using Vulkan Device #" + itos(device_index) + ": " + device_vendor + " - " + device_name); -#endif + device_api_version = gpu_props.apiVersion; err = vkEnumerateDeviceExtensionProperties(gpu, nullptr, &device_extension_count, nullptr); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 4a19f007d4..5209ee06c6 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -62,7 +62,8 @@ void EditorAudioBus::_update_visible_channels() { void EditorAudioBus::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < CHANNELS_MAX; i++) { channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons"))); channel[i].vu_l->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons"))); @@ -86,6 +87,12 @@ void EditorAudioBus::_notification(int p_what) { bus_options->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); + audio_value_preview_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"))); + audio_value_preview_label->add_theme_color_override("font_shadow_color", get_theme_color(SNAME("font_shadow_color"), SNAME("TooltipLabel"))); + audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); + } break; + + case NOTIFICATION_READY: { update_bus(); set_process(true); } break; @@ -157,26 +164,7 @@ void EditorAudioBus::_notification(int p_what) { set_process(is_visible_in_tree()); } break; - case NOTIFICATION_THEME_CHANGED: { - for (int i = 0; i < CHANNELS_MAX; i++) { - channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons"))); - channel[i].vu_l->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons"))); - channel[i].vu_r->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons"))); - channel[i].vu_r->set_progress_texture(get_theme_icon(SNAME("BusVuFull"), SNAME("EditorIcons"))); - channel[i].prev_active = true; - } - - disabled_vu = get_theme_icon(SNAME("BusVuFrozen"), SNAME("EditorIcons")); - - solo->set_icon(get_theme_icon(SNAME("AudioBusSolo"), SNAME("EditorIcons"))); - mute->set_icon(get_theme_icon(SNAME("AudioBusMute"), SNAME("EditorIcons"))); - bypass->set_icon(get_theme_icon(SNAME("AudioBusBypass"), SNAME("EditorIcons"))); - - bus_options->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - audio_value_preview_box->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"))); - audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); - } break; case NOTIFICATION_MOUSE_EXIT: case NOTIFICATION_DRAG_END: { if (hovering_drop) { @@ -833,6 +821,11 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { slider->set_clip_contents(false); audio_value_preview_box = memnew(Panel); + slider->add_child(audio_value_preview_box); + audio_value_preview_box->set_as_top_level(true); + audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS); + audio_value_preview_box->hide(); + HBoxContainer *audioprev_hbc = memnew(HBoxContainer); audioprev_hbc->set_v_size_flags(SIZE_EXPAND_FILL); audioprev_hbc->set_h_size_flags(SIZE_EXPAND_FILL); @@ -842,16 +835,8 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { audio_value_preview_label->set_v_size_flags(SIZE_EXPAND_FILL); audio_value_preview_label->set_h_size_flags(SIZE_EXPAND_FILL); audio_value_preview_label->set_mouse_filter(MOUSE_FILTER_PASS); - audio_value_preview_box->add_theme_color_override("font_color", get_theme_color(SNAME("font_color"), SNAME("TooltipLabel"))); - audioprev_hbc->add_child(audio_value_preview_label); - slider->add_child(audio_value_preview_box); - audio_value_preview_box->set_as_top_level(true); - audio_value_preview_box->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel"))); - audio_value_preview_box->set_mouse_filter(MOUSE_FILTER_PASS); - audio_value_preview_box->hide(); - preview_timer = memnew(Timer); preview_timer->set_wait_time(0.8f); preview_timer->set_one_shot(true); diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 22f44a54bb..72a0c353e8 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -740,7 +740,7 @@ void EditorFeatureProfileManager::_update_selected_profile() { TreeItem *features = class_list->create_item(root); TreeItem *last_feature; - features->set_text(0, TTR("Main Features") + ":"); + features->set_text(0, TTR("Main Features:")); for (int i = 0; i < EditorFeatureProfile::FEATURE_MAX; i++) { TreeItem *feature; if (i == EditorFeatureProfile::FEATURE_IMPORT_DOCK) { @@ -764,7 +764,7 @@ void EditorFeatureProfileManager::_update_selected_profile() { } TreeItem *classes = class_list->create_item(root); - classes->set_text(0, TTR("Nodes and Classes") + ":"); + classes->set_text(0, TTR("Nodes and Classes:")); _fill_classes_from(classes, "Node", class_selected); _fill_classes_from(classes, "Resource", class_selected); @@ -917,7 +917,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { class_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); class_list = memnew(Tree); - class_list_vbc->add_margin_child(TTR("Configure Selected Profile") + ":", class_list, true); + class_list_vbc->add_margin_child(TTR("Configure Selected Profile:"), class_list, true); class_list->set_hide_root(true); class_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); class_list->connect("cell_selected", callable_mp(this, &EditorFeatureProfileManager::_class_list_item_selected)); @@ -931,11 +931,11 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { property_list_vbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); description_bit = memnew(EditorHelpBit); - property_list_vbc->add_margin_child(TTR("Description") + ":", description_bit, false); + property_list_vbc->add_margin_child(TTR("Description:"), description_bit, false); description_bit->set_custom_minimum_size(Size2(0, 80) * EDSCALE); property_list = memnew(Tree); - property_list_vbc->add_margin_child(TTR("Extra Options") + ":", property_list, true); + property_list_vbc->add_margin_child(TTR("Extra Options:"), property_list, true); property_list->set_hide_root(true); property_list->set_hide_folding(true); property_list->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true); @@ -957,7 +957,7 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() { VBoxContainer *new_profile_vb = memnew(VBoxContainer); new_profile_dialog->add_child(new_profile_vb); Label *new_profile_label = memnew(Label); - new_profile_label->set_text(TTR("New profile name") + ":"); + new_profile_label->set_text(TTR("New profile name:")); new_profile_vb->add_child(new_profile_label); new_profile_name = memnew(LineEdit); new_profile_vb->add_child(new_profile_name); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 3db03c0276..4a3413d9ef 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -493,6 +493,7 @@ bool EditorPropertyRevert::is_node_property_different(Node *p_node, const Varian if (ss.is_valid()) { found_state = true; + break; } if (node == edited_scene) { //just in case @@ -506,59 +507,71 @@ bool EditorPropertyRevert::is_node_property_different(Node *p_node, const Varian } } - if (p_current.get_type() == Variant::FLOAT && p_orig.get_type() == Variant::FLOAT) { - float a = p_current; - float b = p_orig; + return is_property_value_different(p_current, p_orig); +} - return !Math::is_equal_approx(a, b); //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error +bool EditorPropertyRevert::is_property_value_different(const Variant &p_a, const Variant &p_b) { + if (p_a.get_type() == Variant::FLOAT && p_b.get_type() == Variant::FLOAT) { + //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error + return !Math::is_equal_approx((float)p_a, (float)p_b); + } else { + return p_a != p_b; } - - return bool(Variant::evaluate(Variant::OP_NOT_EQUAL, p_current, p_orig)); } -bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) { - bool has_revert = false; +Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const StringName &p_property) { + // If the object implements property_can_revert, rely on that completely + // (i.e. don't then try to revert to default value - the property_get_revert implementation + // can do that if so desired) + if (p_object->has_method("property_can_revert") && p_object->call("property_can_revert", p_property)) { + return p_object->call("property_get_revert", p_property); + } + Ref<Script> scr = p_object->get_script(); Node *node = Object::cast_to<Node>(p_object); - if (node && EditorPropertyRevert::may_node_be_in_instance(node)) { - //check for difference including instantiation - Variant vorig; - if (EditorPropertyRevert::get_instantiated_node_original_property(node, p_property, vorig)) { - Variant v = p_object->get(p_property); - - if (EditorPropertyRevert::is_node_property_different(node, v, vorig)) { - has_revert = true; + //if this node is an instance or inherits, but it has a script attached which is unrelated + //to the one set for the parent and also has a default value for the property, consider that + //has precedence over the value from the parent, because that is an explicit source of defaults + //closer in the tree to the current node + bool ignore_parent = false; + if (scr.is_valid()) { + Variant sorig; + if (EditorPropertyRevert::get_instantiated_node_original_property(node, "script", sorig) && !scr->inherits_script(sorig)) { + Variant dummy; + if (scr->get_property_default_value(p_property, dummy)) { + ignore_parent = true; + } } } - } else { - //check for difference against default class value instead - Variant default_value = ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property); - if (default_value != Variant() && default_value != p_object->get(p_property)) { - has_revert = true; + + if (!ignore_parent) { + //check for difference including instantiation + Variant vorig; + if (EditorPropertyRevert::get_instantiated_node_original_property(node, p_property, vorig)) { + return vorig; + } } } - // If the object implements property_can_revert, rely on that completely - // (i.e. don't then try to revert to default value - the property_get_revert implementation - // can do that if so desired) - if (p_object->has_method("property_can_revert")) { - has_revert = p_object->call("property_can_revert", p_property).operator bool(); - } else { - if (!has_revert && !p_object->get_script().is_null()) { - Ref<Script> scr = p_object->get_script(); - if (scr.is_valid()) { - Variant orig_value; - if (scr->get_property_default_value(p_property, orig_value)) { - if (orig_value != p_object->get(p_property)) { - has_revert = true; - } - } - } + if (scr.is_valid()) { + Variant orig_value; + if (scr->get_property_default_value(p_property, orig_value)) { + return orig_value; } } - return has_revert; + //report default class value instead + return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property); +} + +bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) { + Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_object, p_property); + if (revert_value.get_type() == Variant::NIL) { + return false; + } + Variant current_value = p_object->get(p_property); + return EditorPropertyRevert::is_property_value_different(current_value, revert_value); } void EditorProperty::update_reload_status() { @@ -761,41 +774,11 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { } if (revert_rect.has_point(mpos)) { - Variant vorig; - - Node *node = Object::cast_to<Node>(object); - if (node && EditorPropertyRevert::may_node_be_in_instance(node) && EditorPropertyRevert::get_instantiated_node_original_property(node, property, vorig)) { - emit_changed(property, vorig.duplicate(true)); - update_property(); - return; - } - - if (object->call("property_can_revert", property).operator bool()) { - Variant rev = object->call("property_get_revert", property); - emit_changed(property, rev); - update_property(); - return; - } - - if (!object->get_script().is_null()) { - Ref<Script> scr = object->get_script(); - if (scr.is_valid()) { - Variant orig_value; - if (scr->get_property_default_value(property, orig_value)) { - emit_changed(property, orig_value); - update_property(); - return; - } - } - } - - Variant default_value = ClassDB::class_get_default_property_value(object->get_class_name(), property); - if (default_value != Variant()) { - emit_changed(property, default_value); - update_property(); - return; - } + Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property); + emit_changed(property, revert_value); + update_property(); } + if (check_rect.has_point(mpos)) { checked = !checked; update(); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index ee70bd4397..2bb856dc81 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -42,6 +42,8 @@ public: static bool may_node_be_in_instance(Node *p_node); static bool get_instantiated_node_original_property(Node *p_node, const StringName &p_prop, Variant &value); static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig); + static bool is_property_value_different(const Variant &p_a, const Variant &p_b); + static Variant get_property_revert_value(Object *p_object, const StringName &p_property); static bool can_property_revert(Object *p_object, const StringName &p_property); }; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 7d809ea656..9977f5f42c 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -505,7 +505,9 @@ bool EditorResourcePicker::_is_drop_valid(const Dictionary &p_drag_data) const { Ref<Resource> res; if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - res = se->get_edited_resource(); + if (se) { + res = se->get_edited_resource(); + } } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { res = drag_data["resource"]; } @@ -571,7 +573,9 @@ void EditorResourcePicker::drop_data_fw(const Point2 &p_point, const Variant &p_ Ref<Resource> dropped_resource; if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); - dropped_resource = se->get_edited_resource(); + if (se) { + dropped_resource = se->get_edited_resource(); + } } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { dropped_resource = drag_data["resource"]; } diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index c230bdcb73..f0cc1530ab 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -380,6 +380,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color font_color = mono_color.lerp(base_color, 0.25); const Color font_hover_color = mono_color.lerp(base_color, 0.125); const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.3); + const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65); const Color selection_color = accent_color * Color(1, 1, 1, 0.4); const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9); @@ -1028,9 +1029,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled); theme->set_icon("clear", "LineEdit", theme->get_icon("GuiClose", "EditorIcons")); theme->set_color("read_only", "LineEdit", font_disabled_color); - theme->set_color("font_uneditable_color", "LineEdit", font_disabled_color); theme->set_color("font_color", "LineEdit", font_color); theme->set_color("font_selected_color", "LineEdit", mono_color); + theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color); theme->set_color("caret_color", "LineEdit", font_color); theme->set_color("selection_color", "LineEdit", selection_color); theme->set_color("clear_button_color", "LineEdit", font_color); @@ -1196,7 +1197,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { style_tooltip->set_default_margin(SIDE_TOP, default_margin_size * EDSCALE * 0.5); style_tooltip->set_default_margin(SIDE_RIGHT, default_margin_size * EDSCALE); style_tooltip->set_default_margin(SIDE_BOTTOM, default_margin_size * EDSCALE * 0.5); - style_tooltip->set_bg_color(mono_color.inverted()); + style_tooltip->set_bg_color(mono_color.inverted() * Color(1, 1, 1, 0.9)); style_tooltip->set_border_width_all(0); theme->set_color("font_color", "TooltipLabel", font_hover_color); theme->set_color("font_color_shadow", "TooltipLabel", Color(0, 0, 0, 0)); diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp index b32ea67d4d..3fe1aa557d 100644 --- a/editor/localization_editor.cpp +++ b/editor/localization_editor.cpp @@ -371,15 +371,10 @@ void LocalizationEditor::_translation_filter_mode_changed(int p_mode) { void LocalizationEditor::_pot_add(const PackedStringArray &p_paths) { PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations_pot_files"); - for (int i = 0; i < p_paths.size(); i++) { - for (int j = 0; j < pot_translations.size(); j++) { - if (pot_translations[j] == p_paths[i]) { - continue; //exists - } + if (!pot_translations.has(p_paths[i])) { + pot_translations.push_back(p_paths[i]); } - - pot_translations.push_back(p_paths[i]); } undo_redo->create_action(vformat(TTR("Add %d file(s) for POT generation"), p_paths.size())); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index c94014944c..69206daea8 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -89,7 +89,7 @@ Size2 AnimationNodeBlendTreeEditor::get_minimum_size() const { void AnimationNodeBlendTreeEditor::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) { AnimationTree *tree = AnimationTreeEditor::get_singleton()->get_tree(); updating = true; - undo_redo->create_action(TTR("Parameter Changed") + ": " + String(p_property), UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Parameter Changed:") + " " + String(p_property), UndoRedo::MERGE_ENDS); undo_redo->add_do_property(tree, p_property, p_value); undo_redo->add_undo_property(tree, p_property, tree->get(p_property)); undo_redo->add_do_method(this, "_update_graph"); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index cd16353d6a..cf9e94bd3b 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2012,11 +2012,13 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { drag_to = transform.affine_inverse().xform(m->get_position()); Point2 previous_pos; - if (drag_selection.size() == 1) { - Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); - previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); - } else { - previous_pos = _get_encompassing_rect_from_list(drag_selection).position; + if (!drag_selection.is_empty()) { + if (drag_selection.size() == 1) { + Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); + previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); + } else { + previous_pos = _get_encompassing_rect_from_list(drag_selection).position; + } } Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES, 0, nullptr, drag_selection); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index b1f4baac13..af04c9566a 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -1596,8 +1596,14 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { se->gizmo->commit_subgizmos(ids, restore, false); spatial_editor->update_transform_gizmo(); } else { - static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" }; - undo_redo->create_action(_transform_name[_edit.mode]); + static const char *_transform_name[4] = { + TTRC("None"), + TTRC("Rotate"), + // TRANSLATORS: This refers to the movement that changes the position of an object. + TTRC("Translate"), + TTRC("Scale"), + }; + undo_redo->create_action(TTRGET(_transform_name[_edit.mode])); List<Node *> &selection = editor_selection->get_selected_node_list(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 6bcc65e30c..0929a629f8 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -3112,7 +3112,7 @@ void ThemeEditor::edit(const Ref<Theme> &p_theme) { preview_tab->set_preview_theme(p_theme); } - theme_name->set_text(TTR("Theme") + ": " + theme->get_path().get_file()); + theme_name->set_text(TTR("Theme:") + " " + theme->get_path().get_file()); } Ref<Theme> ThemeEditor::get_edited_theme() { @@ -3230,7 +3230,7 @@ ThemeEditor::ThemeEditor() { add_child(top_menu); theme_name = memnew(Label); - theme_name->set_text(TTR("Theme") + ": "); + theme_name->set_text(TTR("Theme:")); theme_name->set_theme_type_variation("HeaderSmall"); top_menu->add_child(theme_name); diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index bbafc7802b..d54906c98c 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -154,7 +154,7 @@ void AtlasMergingDialog::_merge_confirmed(String p_path) { Ref<Texture2D> new_texture_resource = ResourceLoader::load(p_path, "Texture2D"); merged->set_texture(new_texture_resource); - undo_redo->create_action("Merge TileSetAtlasSource"); + undo_redo->create_action(TTR("Merge TileSetAtlasSource")); int next_id = tile_set->get_next_source_id(); undo_redo->add_do_method(*tile_set, "add_source", merged, next_id); undo_redo->add_undo_method(*tile_set, "remove_source", next_id); diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp index e5e7efa531..9e47a44b34 100644 --- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp +++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp @@ -47,7 +47,7 @@ void TileProxiesManagerDialog::_menu_id_pressed(int p_id) { } void TileProxiesManagerDialog::_delete_selected_bindings() { - undo_redo->create_action("Remove Tile Proxies"); + undo_redo->create_action(TTR("Remove Tile Proxies")); Vector<int> source_level_selected = source_level_list->get_selected_items(); for (int i = 0; i < source_level_selected.size(); i++) { @@ -151,7 +151,7 @@ void TileProxiesManagerDialog::_add_button_pressed() { Vector2i to_coords = to.get_atlas_coords(); if (from_coords.x >= 0 && from_coords.y >= 0 && to_coords.x >= 0 && to_coords.y >= 0) { if (from.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE && to.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE) { - undo_redo->create_action("Create Alternative-level Tile Proxy"); + undo_redo->create_action(TTR("Create Alternative-level Tile Proxy")); undo_redo->add_do_method(*tile_set, "set_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile, to.source_id, to.get_atlas_coords(), to.alternative_tile); if (tile_set->has_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile)) { Array a = tile_set->get_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile); @@ -160,7 +160,7 @@ void TileProxiesManagerDialog::_add_button_pressed() { undo_redo->add_undo_method(*tile_set, "remove_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile); } } else { - undo_redo->create_action("Create Coords-level Tile Proxy"); + undo_redo->create_action(TTR("Create Coords-level Tile Proxy")); undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", from.source_id, from.get_atlas_coords(), to.source_id, to.get_atlas_coords()); if (tile_set->has_coords_level_tile_proxy(from.source_id, from.get_atlas_coords())) { Array a = tile_set->get_coords_level_tile_proxy(from.source_id, from.get_atlas_coords()); @@ -170,7 +170,7 @@ void TileProxiesManagerDialog::_add_button_pressed() { } } } else { - undo_redo->create_action("Create source-level Tile Proxy"); + undo_redo->create_action(TTR("Create source-level Tile Proxy")); undo_redo->add_do_method(*tile_set, "set_source_level_tile_proxy", from.source_id, to.source_id); if (tile_set->has_source_level_tile_proxy(from.source_id)) { undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", to.source_id, tile_set->get_source_level_tile_proxy(from.source_id)); @@ -186,7 +186,7 @@ void TileProxiesManagerDialog::_add_button_pressed() { } void TileProxiesManagerDialog::_clear_invalid_button_pressed() { - undo_redo->create_action("Delete All Invalid Tile Proxies"); + undo_redo->create_action(TTR("Delete All Invalid Tile Proxies")); undo_redo->add_do_method(*tile_set, "cleanup_invalid_tile_proxies"); @@ -213,7 +213,7 @@ void TileProxiesManagerDialog::_clear_invalid_button_pressed() { } void TileProxiesManagerDialog::_clear_all_button_pressed() { - undo_redo->create_action("Delete All Tile Proxies"); + undo_redo->create_action(TTR("Delete All Tile Proxies")); undo_redo->add_do_method(*tile_set, "clear_tile_proxies"); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 46818afe45..add75d47fd 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4697,7 +4697,7 @@ public: UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo(); updating = true; - undo_redo->create_action(TTR("Edit Visual Property") + ": " + p_property, UndoRedo::MERGE_ENDS); + undo_redo->create_action(TTR("Edit Visual Property:") + " " + p_property, UndoRedo::MERGE_ENDS); undo_redo->add_do_property(node.ptr(), p_property, p_value); undo_redo->add_undo_property(node.ptr(), p_property, node->get(p_property)); diff --git a/misc/scripts/check_ci_log.py b/misc/scripts/check_ci_log.py index 56c32b154c..2c75b83bd7 100755 --- a/misc/scripts/check_ci_log.py +++ b/misc/scripts/check_ci_log.py @@ -5,7 +5,7 @@ import sys if len(sys.argv) < 2: print("ERROR: You must run program with file name as argument.") - sys.exit(1) + sys.exit(50) fname = sys.argv[1] @@ -17,7 +17,7 @@ file_contents = fileread.read() if file_contents.find("ERROR: AddressSanitizer:") != -1: print("FATAL ERROR: An incorrectly used memory was found.") - sys.exit(1) + sys.exit(51) # There is also possible, that program crashed with or without backtrace. @@ -27,7 +27,7 @@ if ( or file_contents.find("Segmentation fault (core dumped)") != -1 ): print("FATAL ERROR: Godot has been crashed.") - sys.exit(1) + sys.exit(52) # Finding memory leaks in Godot is quite difficult, because we need to take into # account leaks also in external libraries. They are usually provided without @@ -38,7 +38,7 @@ if ( if file_contents.find("ERROR: LeakSanitizer:") != -1: if file_contents.find("#4 0x") != -1: print("ERROR: Memory leak was found") - sys.exit(1) + sys.exit(53) # It may happen that Godot detects leaking nodes/resources and removes them, so # this possibility should also be handled as a potential error, even if @@ -46,7 +46,7 @@ if file_contents.find("ERROR: LeakSanitizer:") != -1: if file_contents.find("ObjectDB instances leaked at exit") != -1: print("ERROR: Memory leak was found") - sys.exit(1) + sys.exit(54) # In test project may be put several assert functions which will control if # project is executed with right parameters etc. which normally will not stop @@ -54,7 +54,7 @@ if file_contents.find("ObjectDB instances leaked at exit") != -1: if file_contents.find("Assertion failed") != -1: print("ERROR: Assertion failed in project, check execution log for more info") - sys.exit(1) + sys.exit(55) # For now Godot leaks a lot of rendering stuff so for now we just show info # about it and this needs to be re-enabled after fixing this memory leaks. diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 1fd656c9b4..399b102284 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -52,7 +52,7 @@ bool GodotFilterCallback::needBroadphaseCollision(btBroadphaseProxy *proxy0, btB } bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); @@ -85,7 +85,7 @@ bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) con return false; } - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (m_exclude->has(gObj->get_self())) { @@ -117,7 +117,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo } bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); if (gObj == m_self_object) { @@ -143,7 +143,7 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox } bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); @@ -180,7 +180,7 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co return false; } - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); @@ -235,7 +235,7 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr return false; } - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); @@ -277,7 +277,7 @@ btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint } bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const { - if (m_collisionFilterGroup & proxy0->m_collisionFilterMask) { + if (proxy0->m_collisionFilterGroup & m_collisionFilterMask) { btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject); CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer()); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 8c286a8629..583900e6bc 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -1133,7 +1133,7 @@ public: virtual bool process(const btBroadphaseProxy *proxy) { btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject); if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) { - if (self_collision_object != proxy->m_clientObject && (collision_layer & proxy->m_collisionFilterMask)) { + if (self_collision_object != proxy->m_clientObject && (proxy->collision_layer & m_collisionFilterMask)) { if (co->getCollisionShape()->isCompound()) { const btCompoundShape *cs = static_cast<btCompoundShape *>(co->getCollisionShape()); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 989c2d295c..f101c43e89 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -675,7 +675,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In } if (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_SELECT) { - undo_redo->create_action("GridMap Selection"); + undo_redo->create_action(TTR("GridMap Selection")); undo_redo->add_do_method(this, "_set_selection", selection.active, selection.begin, selection.end); undo_redo->add_undo_method(this, "_set_selection", last_selection.active, last_selection.begin, last_selection.end); undo_redo->commit_action(); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index fca7985b74..a802e8022d 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -984,7 +984,7 @@ void VisualScriptEditor::_change_port_type(int p_select, int p_id, int p_port, b return; } - undo_redo->create_action("Change Port Type"); + undo_redo->create_action(TTR("Change Port Type")); if (is_input) { undo_redo->add_do_method(vsn.ptr(), "set_input_data_port_type", p_port, Variant::Type(p_select)); undo_redo->add_undo_method(vsn.ptr(), "set_input_data_port_type", p_port, vsn->get_input_value_port_info(p_port).type); @@ -1016,7 +1016,7 @@ void VisualScriptEditor::_port_name_focus_out(const Node *p_name_box, int p_id, return; } - undo_redo->create_action("Change Port Name"); + undo_redo->create_action(TTR("Change Port Name")); if (is_input) { undo_redo->add_do_method(vsn.ptr(), "set_input_data_port_name", p_port, text); undo_redo->add_undo_method(vsn.ptr(), "set_input_data_port_name", p_port, vsn->get_input_value_port_info(p_port).name); diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml index 0e4cc7cfb6..ab7ef6c4d0 100644 --- a/modules/websocket/doc_classes/WebSocketPeer.xml +++ b/modules/websocket/doc_classes/WebSocketPeer.xml @@ -34,6 +34,12 @@ [b]Note:[/b] Not available in the HTML5 export. </description> </method> + <method name="get_current_outbound_buffered_amount" qualifiers="const"> + <return type="int" /> + <description> + Returns the current amount of data in the outbound websocket buffer. [b]Note:[/b] HTML5 exports use WebSocket.bufferedAmount, while other platforms use an internal buffer. + </description> + </method> <method name="get_write_mode" qualifiers="const"> <return type="int" enum="WebSocketPeer.WriteMode" /> <description> diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index d3d0066c12..5cd94e978f 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -95,7 +95,7 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, return FAILED; } - static_cast<Ref<EMWSPeer>>(_peer)->set_sock(_js_id, _in_buf_size, _in_pkt_size); + static_cast<Ref<EMWSPeer>>(_peer)->set_sock(_js_id, _in_buf_size, _in_pkt_size, _out_buf_size); return OK; } @@ -136,6 +136,7 @@ int EMWSClient::get_max_packet_size() const { Error EMWSClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) { _in_buf_size = nearest_shift(p_in_buffer - 1) + 10; _in_pkt_size = nearest_shift(p_in_packets - 1); + _out_buf_size = nearest_shift(p_out_buffer - 1) + 10; return OK; } diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index ca2d7ed986..3b0b8395b9 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -45,6 +45,7 @@ private: bool _is_connecting = false; int _in_buf_size = DEF_BUF_SHIFT; int _in_pkt_size = DEF_PKT_SHIFT; + int _out_buf_size = DEF_BUF_SHIFT; static void _esws_on_connect(void *obj, char *proto); static void _esws_on_message(void *obj, const uint8_t *p_data, int p_data_size, int p_is_string); diff --git a/modules/websocket/emws_peer.cpp b/modules/websocket/emws_peer.cpp index 05f9e12ae1..69822f6ff3 100644 --- a/modules/websocket/emws_peer.cpp +++ b/modules/websocket/emws_peer.cpp @@ -33,10 +33,11 @@ #include "emws_peer.h" #include "core/io/ip.h" -void EMWSPeer::set_sock(int p_sock, unsigned int p_in_buf_size, unsigned int p_in_pkt_size) { +void EMWSPeer::set_sock(int p_sock, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size) { peer_sock = p_sock; _in_buffer.resize(p_in_pkt_size, p_in_buf_size); _packet_buffer.resize((1 << p_in_buf_size)); + _out_buf_size = p_out_buf_size; } void EMWSPeer::set_write_mode(WriteMode p_mode) { @@ -53,7 +54,10 @@ Error EMWSPeer::read_msg(const uint8_t *p_data, uint32_t p_size, bool p_is_strin } Error EMWSPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { + ERR_FAIL_COND_V(_out_buf_size && (godot_js_websocket_buffered_amount(peer_sock) >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY); + int is_bin = write_mode == WebSocketPeer::WRITE_MODE_BINARY ? 1 : 0; + godot_js_websocket_send(peer_sock, p_buffer, p_buffer_size, is_bin); return OK; } @@ -76,6 +80,13 @@ int EMWSPeer::get_available_packet_count() const { return _in_buffer.packets_left(); } +int EMWSPeer::get_current_outbound_buffered_amount() const { + if (peer_sock != -1) { + return godot_js_websocket_buffered_amount(peer_sock); + } + return 0; +} + bool EMWSPeer::was_string_packet() const { return _is_string; } diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index 73e701720b..6e93ea31a2 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -48,6 +48,7 @@ typedef void (*WSOnError)(void *p_ref); extern int godot_js_websocket_create(void *p_ref, const char *p_url, const char *p_proto, WSOnOpen p_on_open, WSOnMessage p_on_message, WSOnError p_on_error, WSOnClose p_on_close); extern int godot_js_websocket_send(int p_id, const uint8_t *p_buf, int p_buf_len, int p_raw); +extern int godot_js_websocket_buffered_amount(int p_id); extern void godot_js_websocket_close(int p_id, int p_code, const char *p_reason); extern void godot_js_websocket_destroy(int p_id); } @@ -62,14 +63,16 @@ private: Vector<uint8_t> _packet_buffer; PacketBuffer<uint8_t> _in_buffer; uint8_t _is_string = 0; + int _out_buf_size = 0; public: Error read_msg(const uint8_t *p_data, uint32_t p_size, bool p_is_string); - void set_sock(int p_sock, unsigned int p_in_buf_size, unsigned int p_in_pkt_size); + void set_sock(int p_sock, unsigned int p_in_buf_size, unsigned int p_in_pkt_size, unsigned int p_out_buf_size); virtual int get_available_packet_count() const; virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size); virtual int get_max_packet_size() const { return _packet_buffer.size(); }; + virtual int get_current_outbound_buffered_amount() const; virtual void close(int p_code = 1000, String p_reason = ""); virtual bool is_connected_to_host() const; diff --git a/modules/websocket/library_godot_websocket.js b/modules/websocket/library_godot_websocket.js index b182d1ecde..dd2fd1e94f 100644 --- a/modules/websocket/library_godot_websocket.js +++ b/modules/websocket/library_godot_websocket.js @@ -101,6 +101,15 @@ const GodotWebSocket = { return 0; }, + // Get current bufferedAmount + bufferedAmount: function (p_id) { + const ref = IDHandler.get(p_id); + if (!ref) { + return 0; // Godot object is gone. + } + return ref.bufferedAmount; + }, + create: function (socket, p_on_open, p_on_message, p_on_error, p_on_close) { const id = IDHandler.add(socket); socket.onopen = GodotWebSocket._onopen.bind(null, id, p_on_open); @@ -171,6 +180,11 @@ const GodotWebSocket = { return GodotWebSocket.send(p_id, out); }, + godot_js_websocket_buffered_amount__sig: 'ii', + godot_js_websocket_buffered_amount: function (p_id) { + return GodotWebSocket.bufferedAmount(p_id); + }, + godot_js_websocket_close__sig: 'viii', godot_js_websocket_close: function (p_id, p_code, p_reason) { const code = p_code; diff --git a/modules/websocket/websocket_peer.cpp b/modules/websocket/websocket_peer.cpp index e77fdcfed2..ee13040821 100644 --- a/modules/websocket/websocket_peer.cpp +++ b/modules/websocket/websocket_peer.cpp @@ -47,6 +47,7 @@ void WebSocketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_connected_host"), &WebSocketPeer::get_connected_host); ClassDB::bind_method(D_METHOD("get_connected_port"), &WebSocketPeer::get_connected_port); ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &WebSocketPeer::set_no_delay); + ClassDB::bind_method(D_METHOD("get_current_outbound_buffered_amount"), &WebSocketPeer::get_current_outbound_buffered_amount); BIND_ENUM_CONSTANT(WRITE_MODE_TEXT); BIND_ENUM_CONSTANT(WRITE_MODE_BINARY); diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index e9bb20f21f..517b8600d6 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -59,6 +59,7 @@ public: virtual uint16_t get_connected_port() const = 0; virtual bool was_string_packet() const = 0; virtual void set_no_delay(bool p_enabled) = 0; + virtual int get_current_outbound_buffered_amount() const = 0; WebSocketPeer(); ~WebSocketPeer(); diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index 1dbadfed74..7f027e1c0d 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -205,7 +205,9 @@ void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigne ERR_FAIL_COND(p_data == nullptr); _in_buffer.resize(p_in_pkt_size, p_in_buf_size); - _packet_buffer.resize((1 << MAX(p_in_buf_size, p_out_buf_size))); + _packet_buffer.resize(1 << p_in_buf_size); + _out_buf_size = p_out_buf_size; + _out_pkt_size = p_out_pkt_size; _data = p_data; _data->peer = this; @@ -239,6 +241,8 @@ void WSLPeer::poll() { Error WSLPeer::put_packet(const uint8_t *p_buffer, int p_buffer_size) { ERR_FAIL_COND_V(!is_connected_to_host(), FAILED); + ERR_FAIL_COND_V(_out_pkt_size && (wslay_event_get_queued_msg_count(_data->ctx) >= (1ULL << _out_pkt_size)), ERR_OUT_OF_MEMORY); + ERR_FAIL_COND_V(_out_buf_size && (wslay_event_get_queued_msg_length(_data->ctx) >= (1ULL << _out_buf_size)), ERR_OUT_OF_MEMORY); struct wslay_event_msg msg; // Should I use fragmented? msg.opcode = write_mode == WRITE_MODE_TEXT ? WSLAY_TEXT_FRAME : WSLAY_BINARY_FRAME; @@ -280,6 +284,12 @@ int WSLPeer::get_available_packet_count() const { return _in_buffer.packets_left(); } +int WSLPeer::get_current_outbound_buffered_amount() const { + ERR_FAIL_COND_V(!_data, 0); + + return wslay_event_get_queued_msg_length(_data->ctx); +} + bool WSLPeer::was_string_packet() const { return _is_string; } diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index f1ea98d384..260d4b183d 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -77,6 +77,9 @@ private: WriteMode write_mode = WRITE_MODE_BINARY; + int _out_buf_size = 0; + int _out_pkt_size = 0; + public: int close_code = -1; String close_reason; @@ -86,6 +89,7 @@ public: virtual Error get_packet(const uint8_t **r_buffer, int &r_buffer_size); virtual Error put_packet(const uint8_t *p_buffer, int p_buffer_size); virtual int get_max_packet_size() const { return _packet_buffer.size(); }; + virtual int get_current_outbound_buffered_amount() const; virtual void close_now(); virtual void close(int p_code = 1000, String p_reason = ""); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index e5d1c2020a..1795bbe523 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -1817,12 +1817,12 @@ public: MutexLock lock(device_lock); - EditorProgress ep("run", "Running on " + devices[p_device].name, 3); + EditorProgress ep("run", vformat(TTR("Running on %s"), devices[p_device].name), 3); String adb = get_adb_path(); // Export_temp APK. - if (ep.step("Exporting APK...", 0)) { + if (ep.step(TTR("Exporting APK..."), 0)) { return ERR_SKIP; } @@ -1857,7 +1857,7 @@ public: String package_name = p_preset->get("package/unique_name"); if (remove_prev) { - if (ep.step("Uninstalling...", 1)) { + if (ep.step(TTR("Uninstalling..."), 1)) { CLEANUP_AND_RETURN(ERR_SKIP); } @@ -1874,7 +1874,7 @@ public: } print_line("Installing to device (please wait...): " + devices[p_device].name); - if (ep.step("Installing to device, please wait...", 2)) { + if (ep.step(TTR("Installing to device, please wait..."), 2)) { CLEANUP_AND_RETURN(ERR_SKIP); } @@ -1889,7 +1889,7 @@ public: err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error("Could not install to device: " + output); + EditorNode::add_io_error(vformat(TTR("Could not install to device: %s"), output)); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -1945,7 +1945,7 @@ public: } } - if (ep.step("Running on device...", 3)) { + if (ep.step(TTR("Running on device..."), 3)) { CLEANUP_AND_RETURN(ERR_SKIP); } args.clear(); @@ -1967,7 +1967,7 @@ public: err = OS::get_singleton()->execute(adb, args, &output, &rv, true); print_verbose(output); if (err || rv != 0) { - EditorNode::add_io_error("Could not execute on device."); + EditorNode::add_io_error(TTR("Could not execute on device.")); CLEANUP_AND_RETURN(ERR_CANT_CREATE); } @@ -2326,7 +2326,7 @@ public: String apksigner = get_apksigner_path(); print_verbose("Starting signing of the " + export_label + " binary using " + apksigner); if (!FileAccess::exists(apksigner)) { - EditorNode::add_io_error("'apksigner' could not be found.\nPlease check the command is available in the Android SDK build-tools directory.\nThe resulting " + export_label + " is unsigned."); + EditorNode::add_io_error(vformat(TTR("'apksigner' could not be found.\nPlease check the command is available in the Android SDK build-tools directory.\nThe resulting %s is unsigned."), export_label)); return OK; } @@ -2344,7 +2344,7 @@ public: user = EditorSettings::get_singleton()->get("export/android/debug_keystore_user"); } - if (ep.step("Signing debug " + export_label + "...", 104)) { + if (ep.step(vformat(TTR("Signing debug %s..."), export_label), 104)) { return ERR_SKIP; } @@ -2353,13 +2353,13 @@ public: password = release_password; user = release_username; - if (ep.step("Signing release " + export_label + "...", 104)) { + if (ep.step(vformat(TTR("Signing release %s..."), export_label), 104)) { return ERR_SKIP; } } if (!FileAccess::exists(keystore)) { - EditorNode::add_io_error("Could not find keystore, unable to export."); + EditorNode::add_io_error(TTR("Could not find keystore, unable to export.")); return ERR_FILE_CANT_OPEN; } @@ -2383,11 +2383,11 @@ public: OS::get_singleton()->execute(apksigner, args, &output, &retval, true); print_verbose(output); if (retval) { - EditorNode::add_io_error("'apksigner' returned with error #" + itos(retval)); + EditorNode::add_io_error(vformat(TTR("'apksigner' returned with error #%d"), retval)); return ERR_CANT_CREATE; } - if (ep.step("Verifying " + export_label + "...", 105)) { + if (ep.step(vformat(TTR("Verifying %s..."), export_label), 105)) { return ERR_SKIP; } @@ -2403,7 +2403,7 @@ public: OS::get_singleton()->execute(apksigner, args, &output, &retval, true); print_verbose(output); if (retval) { - EditorNode::add_io_error("'apksigner' verification of " + export_label + " failed."); + EditorNode::add_io_error(vformat(TTR("'apksigner' verification of %s failed."), export_label)); return ERR_CANT_CREATE; } @@ -2466,7 +2466,7 @@ public: String src_apk; Error err; - EditorProgress ep("export", "Exporting for Android", 105, true); + EditorProgress ep("export", TTR("Exporting for Android"), 105, true); bool use_custom_build = bool(p_preset->get("custom_template/use_custom_build")); bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG); @@ -2515,7 +2515,7 @@ public: return ERR_UNCONFIGURED; } if (export_format > EXPORT_FORMAT_AAB || export_format < EXPORT_FORMAT_APK) { - EditorNode::add_io_error("Unsupported export format!\n"); + EditorNode::add_io_error(TTR("Unsupported export format!\n")); return ERR_UNCONFIGURED; //TODO: is this the right error? } @@ -2545,7 +2545,7 @@ public: String project_name = get_project_name(p_preset->get("package/name")); err = _create_project_name_strings_files(p_preset, project_name); //project name localization. if (err != OK) { - EditorNode::add_io_error("Unable to overwrite res://android/build/res/*.xml files with project name"); + EditorNode::add_io_error(TTR("Unable to overwrite res://android/build/res/*.xml files with project name")); } // Copies the project icon files into the appropriate Gradle project directory. _copy_icons_to_gradle_project(p_preset, processed_splash_config_xml, splash_image, splash_bg_color_image, main_image, foreground, background); @@ -2561,7 +2561,7 @@ public: user_data.debug = p_debug; err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so); if (err != OK) { - EditorNode::add_io_error("Could not export project files to gradle project\n"); + EditorNode::add_io_error(TTR("Could not export project files to gradle project\n")); return err; } if (user_data.libs.size() > 0) { @@ -2574,7 +2574,7 @@ public: print_verbose("Saving apk expansion file.."); err = save_apk_expansion_file(p_preset, p_path); if (err != OK) { - EditorNode::add_io_error("Could not write expansion package file!"); + EditorNode::add_io_error(TTR("Could not write expansion package file!")); return err; } } @@ -2661,7 +2661,7 @@ public: String release_username = p_preset->get("keystore/release_user"); String release_password = p_preset->get("keystore/release_password"); if (!FileAccess::exists(release_keystore)) { - EditorNode::add_io_error("Could not find keystore, unable to export."); + EditorNode::add_io_error(TTR("Could not find keystore, unable to export.")); return ERR_FILE_CANT_OPEN; } @@ -2725,7 +2725,7 @@ public: src_apk = find_export_template("android_release.apk"); } if (src_apk == "") { - EditorNode::add_io_error("Package not found: " + src_apk); + EditorNode::add_io_error(vformat(TTR("Package not found: %s"), src_apk)); return ERR_FILE_NOT_FOUND; } } @@ -2737,13 +2737,13 @@ public: FileAccess *src_f = nullptr; zlib_filefunc_def io = zipio_create_io_from_file(&src_f); - if (ep.step("Creating APK...", 0)) { + if (ep.step(TTR("Creating APK..."), 0)) { return ERR_SKIP; } unzFile pkg = unzOpen2(src_apk.utf8().get_data(), &io); if (!pkg) { - EditorNode::add_io_error("Could not find template APK to export:\n" + src_apk); + EditorNode::add_io_error(vformat(TTR("Could not find template APK to export:\n%s"), src_apk)); return ERR_FILE_NOT_FOUND; } @@ -2871,12 +2871,11 @@ public: if (!invalid_abis.is_empty()) { String unsupported_arch = String(", ").join(invalid_abis); - EditorNode::add_io_error("Missing libraries in the export template for the selected architectures: " + unsupported_arch + ".\n" + - "Please build a template with all required libraries, or uncheck the missing architectures in the export preset."); + EditorNode::add_io_error(vformat(TTR("Missing libraries in the export template for the selected architectures: %s.\nPlease build a template with all required libraries, or uncheck the missing architectures in the export preset."), unsupported_arch)); CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); } - if (ep.step("Adding files...", 1)) { + if (ep.step(TTR("Adding files..."), 1)) { CLEANUP_AND_RETURN(ERR_SKIP); } err = OK; @@ -2890,7 +2889,7 @@ public: if (apk_expansion) { err = save_apk_expansion_file(p_preset, p_path); if (err != OK) { - EditorNode::add_io_error("Could not write expansion package file!"); + EditorNode::add_io_error(TTR("Could not write expansion package file!")); return err; } } else { @@ -2903,7 +2902,7 @@ public: if (err != OK) { unzClose(pkg); - EditorNode::add_io_error("Could not export project files"); + EditorNode::add_io_error(TTR("Could not export project files")); CLEANUP_AND_RETURN(ERR_SKIP); } @@ -2933,13 +2932,13 @@ public: // If we're not signing the apk, then the next step should be the last. const int next_step = should_sign ? 103 : 105; - if (ep.step("Aligning APK...", next_step)) { + if (ep.step(TTR("Aligning APK..."), next_step)) { CLEANUP_AND_RETURN(ERR_SKIP); } unzFile tmp_unaligned = unzOpen2(tmp_unaligned_path.utf8().get_data(), &io); if (!tmp_unaligned) { - EditorNode::add_io_error("Could not unzip temporary unaligned APK."); + EditorNode::add_io_error(TTR("Could not unzip temporary unaligned APK.")); CLEANUP_AND_RETURN(ERR_FILE_NOT_FOUND); } diff --git a/platform/windows/detect.py b/platform/windows/detect.py index a94f38583c..287ece1d29 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -152,7 +152,7 @@ def setup_msvc_auto(env): env["TARGET_ARCH"] = None if env["bits"] != "default": env["TARGET_ARCH"] = {"32": "x86", "64": "x86_64"}[env["bits"]] - if env.has_key("msvc_version"): + if "msvc_version" in env: env["MSVC_VERSION"] = env["msvc_version"] env.Tool("msvc") env.Tool("mssdk") # we want the MS SDK diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 71d985a6c5..91d747b492 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -226,16 +226,16 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) { } bool BodyPair2DSW::setup(real_t p_step) { - dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); - dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); - if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; } + collide_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) && A->collides_with(B); + collide_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) && B->collides_with(A); + report_contacts_only = false; - if (!dynamic_A && !dynamic_B) { + if (!collide_A && !collide_B) { if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) { report_contacts_only = true; } else { @@ -275,13 +275,13 @@ bool BodyPair2DSW::setup(real_t p_step) { if (!collided) { //test ccd (currently just a raycast) - if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && dynamic_A) { + if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_A) { if (_test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B)) { collided = true; } } - if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && dynamic_B) { + if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && collide_B) { if (_test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A, true)) { collided = true; } @@ -374,6 +374,12 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { const Transform2D &transform_A = A->get_transform(); const Transform2D &transform_B = B->get_transform(); + real_t inv_inertia_A = collide_A ? A->get_inv_inertia() : 0.0; + real_t inv_inertia_B = collide_B ? B->get_inv_inertia() : 0.0; + + real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0; + real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0; + for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; c.active = false; @@ -384,7 +390,7 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { Vector2 axis = global_A - global_B; real_t depth = axis.dot(c.normal); - if (depth <= 0 || !c.reused) { + if (depth <= 0.0 || !c.reused) { continue; } @@ -416,15 +422,15 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { // Precompute normal mass, tangent mass, and bias. real_t rnA = c.rA.dot(c.normal); real_t rnB = c.rB.dot(c.normal); - real_t kNormal = A->get_inv_mass() + B->get_inv_mass(); - kNormal += A->get_inv_inertia() * (c.rA.dot(c.rA) - rnA * rnA) + B->get_inv_inertia() * (c.rB.dot(c.rB) - rnB * rnB); + real_t kNormal = inv_mass_A + inv_mass_B; + kNormal += inv_inertia_A * (c.rA.dot(c.rA) - rnA * rnA) + inv_inertia_B * (c.rB.dot(c.rB) - rnB * rnB); c.mass_normal = 1.0f / kNormal; Vector2 tangent = c.normal.orthogonal(); real_t rtA = c.rA.dot(tangent); real_t rtB = c.rB.dot(tangent); - real_t kTangent = A->get_inv_mass() + B->get_inv_mass(); - kTangent += A->get_inv_inertia() * (c.rA.dot(c.rA) - rtA * rtA) + B->get_inv_inertia() * (c.rB.dot(c.rB) - rtB * rtB); + real_t kTangent = inv_mass_A + inv_mass_B; + kTangent += inv_inertia_A * (c.rA.dot(c.rA) - rtA * rtA) + inv_inertia_B * (c.rB.dot(c.rB) - rtB * rtB); c.mass_tangent = 1.0f / kTangent; c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration); @@ -436,10 +442,10 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { // Apply normal + friction impulse Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent; - if (dynamic_A) { + if (collide_A) { A->apply_impulse(-P, c.rA); } - if (dynamic_B) { + if (collide_B) { B->apply_impulse(P, c.rB); } } @@ -493,10 +499,10 @@ void BodyPair2DSW::solve(real_t p_step) { Vector2 jb = c.normal * (c.acc_bias_impulse - jbnOld); - if (dynamic_A) { + if (collide_A) { A->apply_bias_impulse(-jb, c.rA); } - if (dynamic_B) { + if (collide_B) { B->apply_bias_impulse(jb, c.rB); } @@ -513,10 +519,10 @@ void BodyPair2DSW::solve(real_t p_step) { Vector2 j = c.normal * (c.acc_normal_impulse - jnOld) + tangent * (c.acc_tangent_impulse - jtOld); - if (dynamic_A) { + if (collide_A) { A->apply_impulse(-j, c.rA); } - if (dynamic_B) { + if (collide_B) { B->apply_impulse(j, c.rB); } } diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h index 4b42b44c92..849a7e2430 100644 --- a/servers/physics_2d/body_pair_2d_sw.h +++ b/servers/physics_2d/body_pair_2d_sw.h @@ -50,8 +50,8 @@ class BodyPair2DSW : public Constraint2DSW { int shape_A = 0; int shape_B = 0; - bool dynamic_A = false; - bool dynamic_B = false; + bool collide_A = false; + bool collide_B = false; Space2DSW *space = nullptr; diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 14adb0bb18..55ffa9b1b8 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -186,8 +186,8 @@ public: void set_pickable(bool p_pickable) { pickable = p_pickable; } _FORCE_INLINE_ bool is_pickable() const { return pickable; } - _FORCE_INLINE_ bool layer_in_mask(CollisionObject2DSW *p_other) const { - return collision_layer & p_other->collision_mask; + _FORCE_INLINE_ bool collides_with(CollisionObject2DSW *p_other) const { + return p_other->collision_layer & collision_mask; } _FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const { diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 43329fed2f..590c93a7be 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -508,7 +508,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { keep = false; } else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) { keep = false; - } else if (!p_body->layer_in_mask(static_cast<Body2DSW *>(intersection_query_results[i]))) { + } else if (!p_body->collides_with(static_cast<Body2DSW *>(intersection_query_results[i]))) { keep = false; } else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { keep = false; diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp index af680f23db..c27a2ecced 100644 --- a/servers/physics_3d/body_pair_3d_sw.cpp +++ b/servers/physics_3d/body_pair_3d_sw.cpp @@ -212,16 +212,16 @@ real_t combine_friction(Body3DSW *A, Body3DSW *B) { } bool BodyPair3DSW::setup(real_t p_step) { - dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); - dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); - if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; } + collide_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && A->collides_with(B); + collide_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && B->collides_with(A); + report_contacts_only = false; - if (!dynamic_A && !dynamic_B) { + if (!collide_A && !collide_B) { if ((A->get_max_contacts_reported() > 0) || (B->get_max_contacts_reported() > 0)) { report_contacts_only = true; } else { @@ -250,11 +250,11 @@ bool BodyPair3DSW::setup(real_t p_step) { if (!collided) { //test ccd (currently just a raycast) - if (A->is_continuous_collision_detection_enabled() && dynamic_A && !dynamic_B) { + if (A->is_continuous_collision_detection_enabled() && collide_A) { _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B); } - if (B->is_continuous_collision_detection_enabled() && dynamic_B && !dynamic_A) { + if (B->is_continuous_collision_detection_enabled() && collide_B) { _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A); } @@ -293,6 +293,15 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { const Basis &basis_A = A->get_transform().basis; const Basis &basis_B = B->get_transform().basis; + Basis zero_basis; + zero_basis.set_zero(); + + const Basis &inv_inertia_tensor_A = collide_A ? A->get_inv_inertia_tensor() : zero_basis; + const Basis &inv_inertia_tensor_B = collide_B ? B->get_inv_inertia_tensor() : zero_basis; + + real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0; + real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0; + for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; c.active = false; @@ -303,7 +312,7 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { Vector3 axis = global_A - global_B; real_t depth = axis.dot(c.normal); - if (depth <= 0) { + if (depth <= 0.0) { continue; } @@ -339,9 +348,9 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { do_process = true; // Precompute normal mass, tangent mass, and bias. - Vector3 inertia_A = A->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); - Vector3 inertia_B = B->get_inv_inertia_tensor().xform(c.rB.cross(c.normal)); - real_t kNormal = A->get_inv_mass() + B->get_inv_mass(); + Vector3 inertia_A = inv_inertia_tensor_A.xform(c.rA.cross(c.normal)); + Vector3 inertia_B = inv_inertia_tensor_B.xform(c.rB.cross(c.normal)); + real_t kNormal = inv_mass_A + inv_mass_B; kNormal += c.normal.dot(inertia_A.cross(c.rA)) + c.normal.dot(inertia_B.cross(c.rB)); c.mass_normal = 1.0f / kNormal; @@ -349,10 +358,10 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { c.depth = depth; Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; - if (dynamic_A) { + if (collide_A) { A->apply_impulse(-j_vec, c.rA + A->get_center_of_mass()); } - if (dynamic_B) { + if (collide_B) { B->apply_impulse(j_vec, c.rB + B->get_center_of_mass()); } c.acc_bias_impulse = 0; @@ -378,6 +387,15 @@ void BodyPair3DSW::solve(real_t p_step) { const real_t max_bias_av = MAX_BIAS_ROTATION / p_step; + Basis zero_basis; + zero_basis.set_zero(); + + const Basis &inv_inertia_tensor_A = collide_A ? A->get_inv_inertia_tensor() : zero_basis; + const Basis &inv_inertia_tensor_B = collide_B ? B->get_inv_inertia_tensor() : zero_basis; + + real_t inv_mass_A = collide_A ? A->get_inv_mass() : 0.0; + real_t inv_mass_B = collide_B ? B->get_inv_mass() : 0.0; + for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; if (!c.active) { @@ -401,10 +419,10 @@ void BodyPair3DSW::solve(real_t p_step) { Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); - if (dynamic_A) { + if (collide_A) { A->apply_bias_impulse(-jb, c.rA + A->get_center_of_mass(), max_bias_av); } - if (dynamic_B) { + if (collide_B) { B->apply_bias_impulse(jb, c.rB + B->get_center_of_mass(), max_bias_av); } @@ -415,16 +433,16 @@ void BodyPair3DSW::solve(real_t p_step) { vbn = dbv.dot(c.normal); if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { - real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass()); + real_t jbn_com = (-vbn + c.bias) / (inv_mass_A + inv_mass_B); real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); - if (dynamic_A) { + if (collide_A) { A->apply_bias_impulse(-jb_com, A->get_center_of_mass(), 0.0f); } - if (dynamic_B) { + if (collide_B) { B->apply_bias_impulse(jb_com, B->get_center_of_mass(), 0.0f); } } @@ -446,10 +464,10 @@ void BodyPair3DSW::solve(real_t p_step) { Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); - if (dynamic_A) { + if (collide_A) { A->apply_impulse(-j, c.rA + A->get_center_of_mass()); } - if (dynamic_B) { + if (collide_B) { B->apply_impulse(j, c.rB + B->get_center_of_mass()); } @@ -473,11 +491,11 @@ void BodyPair3DSW::solve(real_t p_step) { if (tvl > MIN_VELOCITY) { tv /= tvl; - Vector3 temp1 = A->get_inv_inertia_tensor().xform(c.rA.cross(tv)); - Vector3 temp2 = B->get_inv_inertia_tensor().xform(c.rB.cross(tv)); + Vector3 temp1 = inv_inertia_tensor_A.xform(c.rA.cross(tv)); + Vector3 temp2 = inv_inertia_tensor_B.xform(c.rB.cross(tv)); real_t t = -tvl / - (A->get_inv_mass() + B->get_inv_mass() + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB))); + (inv_mass_A + inv_mass_B + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB))); Vector3 jt = t * tv; @@ -493,10 +511,10 @@ void BodyPair3DSW::solve(real_t p_step) { jt = c.acc_tangent_impulse - jtOld; - if (dynamic_A) { + if (collide_A) { A->apply_impulse(-jt, c.rA + A->get_center_of_mass()); } - if (dynamic_B) { + if (collide_B) { B->apply_impulse(jt, c.rB + B->get_center_of_mass()); } @@ -595,13 +613,23 @@ void BodySoftBodyPair3DSW::validate_contacts() { } bool BodySoftBodyPair3DSW::setup(real_t p_step) { - body_dynamic = (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); - if (!body->interacts_with(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) { collided = false; return false; } + body_collides = (body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) && body->collides_with(soft_body); + soft_body_collides = soft_body->collides_with(body); + + if (!body_collides && !soft_body_collides) { + if (body->get_max_contacts_reported() > 0) { + report_contacts_only = true; + } else { + collided = false; + return false; + } + } + const Transform3D &xform_Au = body->get_transform(); Transform3D xform_A = xform_Au * body->get_shape_transform(body_shape); @@ -639,13 +667,20 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { const Transform3D &transform_A = body->get_transform(); + Basis zero_basis; + zero_basis.set_zero(); + + const Basis &body_inv_inertia_tensor = body_collides ? body->get_inv_inertia_tensor() : zero_basis; + + real_t body_inv_mass = body_collides ? body->get_inv_mass() : 0.0; + uint32_t contact_count = contacts.size(); for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { Contact &c = contacts[contact_index]; c.active = false; - real_t node_inv_mass = soft_body->get_node_inv_mass(c.index_B); - if (node_inv_mass == 0.0) { + real_t node_inv_mass = soft_body_collides ? soft_body->get_node_inv_mass(c.index_B) : 0.0; + if ((node_inv_mass == 0.0) && (body_inv_mass == 0.0)) { continue; } @@ -654,15 +689,11 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { Vector3 axis = global_A - global_B; real_t depth = axis.dot(c.normal); - if (depth <= 0) { + if (depth <= 0.0) { continue; } - c.active = true; - do_process = true; - #ifdef DEBUG_ENABLED - if (space->is_debugging_contacts()) { space->add_debug_contact(global_A); space->add_debug_contact(global_B); @@ -677,13 +708,21 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { body->add_contact(global_A, -c.normal, depth, body_shape, global_B, 0, soft_body->get_instance_id(), soft_body->get_self(), crA); } - if (body_dynamic) { + if (report_contacts_only) { + collided = false; + continue; + } + + c.active = true; + do_process = true; + + if (body_collides) { body->set_active(true); } // Precompute normal mass, tangent mass, and bias. - Vector3 inertia_A = body->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); - real_t kNormal = body->get_inv_mass() + node_inv_mass; + Vector3 inertia_A = body_inv_inertia_tensor.xform(c.rA.cross(c.normal)); + real_t kNormal = body_inv_mass + node_inv_mass; kNormal += c.normal.dot(inertia_A.cross(c.rA)); c.mass_normal = 1.0f / kNormal; @@ -691,10 +730,12 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { c.depth = depth; Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; - if (body_dynamic) { + if (body_collides) { body->apply_impulse(-j_vec, c.rA + body->get_center_of_mass()); } - soft_body->apply_node_impulse(c.index_B, j_vec); + if (soft_body_collides) { + soft_body->apply_node_impulse(c.index_B, j_vec); + } c.acc_bias_impulse = 0; c.acc_bias_impulse_center_of_mass = 0; @@ -719,6 +760,13 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { const real_t max_bias_av = MAX_BIAS_ROTATION / p_step; + Basis zero_basis; + zero_basis.set_zero(); + + const Basis &body_inv_inertia_tensor = body_collides ? body->get_inv_inertia_tensor() : zero_basis; + + real_t body_inv_mass = body_collides ? body->get_inv_mass() : 0.0; + uint32_t contact_count = contacts.size(); for (uint32_t contact_index = 0; contact_index < contact_count; ++contact_index) { Contact &c = contacts[contact_index]; @@ -728,6 +776,8 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { c.active = false; + real_t node_inv_mass = soft_body_collides ? soft_body->get_node_inv_mass(c.index_B) : 0.0; + // Bias impulse. Vector3 crbA = body->get_biased_angular_velocity().cross(c.rA); Vector3 dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA; @@ -741,10 +791,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); - if (body_dynamic) { + if (body_collides) { body->apply_bias_impulse(-jb, c.rA + body->get_center_of_mass(), max_bias_av); } - soft_body->apply_node_bias_impulse(c.index_B, jb); + if (soft_body_collides) { + soft_body->apply_node_bias_impulse(c.index_B, jb); + } crbA = body->get_biased_angular_velocity().cross(c.rA); dbv = soft_body->get_node_biased_velocity(c.index_B) - body->get_biased_linear_velocity() - crbA; @@ -752,16 +804,18 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { vbn = dbv.dot(c.normal); if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { - real_t jbn_com = (-vbn + c.bias) / (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B)); + real_t jbn_com = (-vbn + c.bias) / (body_inv_mass + node_inv_mass); real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); - if (body_dynamic) { + if (body_collides) { body->apply_bias_impulse(-jb_com, body->get_center_of_mass(), 0.0f); } - soft_body->apply_node_bias_impulse(c.index_B, jb_com); + if (soft_body_collides) { + soft_body->apply_node_bias_impulse(c.index_B, jb_com); + } } c.active = true; @@ -780,10 +834,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); - if (body_dynamic) { + if (body_collides) { body->apply_impulse(-j, c.rA + body->get_center_of_mass()); } - soft_body->apply_node_impulse(c.index_B, j); + if (soft_body_collides) { + soft_body->apply_node_impulse(c.index_B, j); + } c.active = true; } @@ -804,10 +860,10 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { if (tvl > MIN_VELOCITY) { tv /= tvl; - Vector3 temp1 = body->get_inv_inertia_tensor().xform(c.rA.cross(tv)); + Vector3 temp1 = body_inv_inertia_tensor.xform(c.rA.cross(tv)); real_t t = -tvl / - (body->get_inv_mass() + soft_body->get_node_inv_mass(c.index_B) + tv.dot(temp1.cross(c.rA))); + (body_inv_mass + node_inv_mass + tv.dot(temp1.cross(c.rA))); Vector3 jt = t * tv; @@ -823,10 +879,12 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { jt = c.acc_tangent_impulse - jtOld; - if (body_dynamic) { + if (body_collides) { body->apply_impulse(-jt, c.rA + body->get_center_of_mass()); } - soft_body->apply_node_impulse(c.index_B, jt); + if (soft_body_collides) { + soft_body->apply_node_impulse(c.index_B, jt); + } c.active = true; } diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h index 976982d1f1..19d6a46880 100644 --- a/servers/physics_3d/body_pair_3d_sw.h +++ b/servers/physics_3d/body_pair_3d_sw.h @@ -83,8 +83,8 @@ class BodyPair3DSW : public BodyContact3DSW { int shape_A = 0; int shape_B = 0; - bool dynamic_A = false; - bool dynamic_B = false; + bool collide_A = false; + bool collide_B = false; bool report_contacts_only = false; @@ -115,7 +115,10 @@ class BodySoftBodyPair3DSW : public BodyContact3DSW { int body_shape = 0; - bool body_dynamic = false; + bool body_collides = false; + bool soft_body_collides = false; + + bool report_contacts_only = false; LocalVector<Contact> contacts; diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h index fb8dca8bb4..6ffab54645 100644 --- a/servers/physics_3d/collision_object_3d_sw.h +++ b/servers/physics_3d/collision_object_3d_sw.h @@ -166,8 +166,8 @@ public: } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } - _FORCE_INLINE_ bool layer_in_mask(CollisionObject3DSW *p_other) const { - return collision_layer & p_other->collision_mask; + _FORCE_INLINE_ bool collides_with(CollisionObject3DSW *p_other) const { + return p_other->collision_layer & collision_mask; } _FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const { diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index bc149648d7..1037243d3b 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -549,7 +549,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { keep = false; } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) { keep = false; - } else if (!p_body->layer_in_mask(static_cast<Body3DSW *>(intersection_query_results[i]))) { + } else if (!p_body->collides_with(static_cast<Body3DSW *>(intersection_query_results[i]))) { keep = false; } else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { keep = false; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index a7ee0dd141..02d548bf13 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -222,7 +222,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color RD::get_singleton()->swap_buffers(); - RD::get_singleton()->free(texture); + storage->free(texture); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index 1b9f54d1c8..5bb12fc168 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -146,7 +146,9 @@ void ShaderRD::_clear_version(Version *p_version) { //clear versions if they exist if (p_version->variants) { for (int i = 0; i < variant_defines.size(); i++) { - RD::get_singleton()->free(p_version->variants[i]); + if (variants_enabled[i]) { + RD::get_singleton()->free(p_version->variants[i]); + } } memdelete_arr(p_version->variants); |