summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux_builds.yml18
-rw-r--r--core/math/math_funcs.cpp10
-rw-r--r--core/math/math_funcs.h1
-rw-r--r--core/variant/variant_parser.h6
-rw-r--r--core/variant/variant_utility.cpp5
-rw-r--r--doc/classes/@GlobalScope.xml13
-rw-r--r--doc/classes/CollisionObject2D.xml4
-rw-r--r--doc/classes/CollisionObject3D.xml8
-rw-r--r--doc/classes/SoftBody3D.xml8
-rw-r--r--drivers/vulkan/vulkan_context.cpp31
-rw-r--r--editor/editor_audio_buses.cpp41
-rw-r--r--editor/editor_feature_profile.cpp12
-rw-r--r--editor/editor_inspector.cpp127
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/editor_themes.cpp5
-rw-r--r--editor/import/editor_importer_bake_reset.cpp223
-rw-r--r--editor/import/editor_importer_bake_reset.h54
-rw-r--r--editor/import/resource_importer_scene.cpp7
-rw-r--r--editor/localization_editor.cpp9
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/theme_editor_plugin.cpp4
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp2
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp12
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp2
-rwxr-xr-xmisc/scripts/check_ci_log.py12
-rw-r--r--modules/bullet/godot_result_callbacks.cpp14
-rw-r--r--modules/bullet/space_bullet.cpp2
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs10
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml77
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp23
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h1
-rw-r--r--modules/visual_script/visual_script_editor.cpp4
-rw-r--r--scene/2d/camera_2d.cpp2
-rw-r--r--scene/resources/resource_format_text.cpp1
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp40
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h4
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h4
-rw-r--r--servers/physics_2d/space_2d_sw.cpp2
-rw-r--r--servers/physics_3d/body_pair_3d_sw.cpp156
-rw-r--r--servers/physics_3d/body_pair_3d_sw.h9
-rw-r--r--servers/physics_3d/collision_object_3d_sw.h4
-rw-r--r--servers/physics_3d/space_3d_sw.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp4
46 files changed, 622 insertions, 369 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/math_funcs.cpp b/core/math/math_funcs.cpp
index e92bb9f4aa..bbed257f60 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -88,16 +88,6 @@ int Math::range_step_decimals(double p_step) {
return step_decimals(p_step);
}
-double Math::dectime(double p_value, double p_amount, double p_step) {
- double sgn = p_value < 0 ? -1.0 : 1.0;
- double val = Math::abs(p_value);
- val -= p_amount * p_step;
- if (val < 0.0) {
- val = 0.0;
- }
- return val * sgn;
-}
-
double Math::ease(double p_x, double p_c) {
if (p_x < 0) {
p_x = 0;
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 3389407e72..4e4f566517 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -296,7 +296,6 @@ public:
static int step_decimals(double p_step);
static int range_step_decimals(double p_step);
static double snapped(double p_value, double p_step);
- static double dectime(double p_value, double p_amount, double p_step);
static uint32_t larger_prime(uint32_t p_val);
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 05fc29b5e0..1ba26db6ed 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -73,9 +73,9 @@ public:
struct ResourceParser {
void *userdata = nullptr;
- ParseResourceFunc func;
- ParseResourceFunc ext_func;
- ParseResourceFunc sub_func;
+ ParseResourceFunc func = nullptr;
+ ParseResourceFunc ext_func = nullptr;
+ ParseResourceFunc sub_func = nullptr;
};
enum TokenType {
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 64f07e075e..34dbf130b6 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -249,10 +249,6 @@ struct VariantUtilityFunctions {
return Math::move_toward(from, to, delta);
}
- static inline double dectime(double value, double amount, double step) {
- return Math::dectime(value, amount, step);
- }
-
static inline double deg2rad(double angle_deg) {
return Math::deg2rad(angle_deg);
}
@@ -1195,7 +1191,6 @@ void Variant::_register_variant_utility_functions() {
FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH);
- FUNCBINDR(dectime, sarray("value", "amount", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(deg2rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH);
FUNCBINDR(rad2deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH);
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 33d877af29..c86812742c 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -193,19 +193,6 @@
Converts from decibels to linear energy (audio).
</description>
</method>
- <method name="dectime">
- <return type="float" />
- <argument index="0" name="value" type="float" />
- <argument index="1" name="amount" type="float" />
- <argument index="2" name="step" type="float" />
- <description>
- Returns the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code].
- [codeblock]
- # a = 59
- a = dectime(60, 10, 0.1))
- [/codeblock]
- </description>
- </method>
<method name="deg2rad">
<return type="float" />
<argument index="0" name="deg" type="float" />
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_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/import/editor_importer_bake_reset.cpp b/editor/import/editor_importer_bake_reset.cpp
new file mode 100644
index 0000000000..939c47faa4
--- /dev/null
+++ b/editor/import/editor_importer_bake_reset.cpp
@@ -0,0 +1,223 @@
+/*************************************************************************/
+/* editor_importer_bake_reset.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor/import/editor_importer_bake_reset.h"
+
+#include "core/error/error_macros.h"
+#include "core/math/transform_3d.h"
+#include "editor/import/scene_importer_mesh_node_3d.h"
+#include "resource_importer_scene.h"
+#include "scene/3d/mesh_instance_3d.h"
+#include "scene/3d/node_3d.h"
+#include "scene/3d/skeleton_3d.h"
+#include "scene/animation/animation_player.h"
+
+// Given that an engineering team has made a reference character, one wants ten animators to create animations.
+// Currently, a tech artist needs to combine the ten files into one exported gltf2 to import into Godot Engine.
+// We bake the RESET animation and then set it to identity,
+// so that rigs with corresponding RESET animation can have their animations transferred with ease.
+//
+// The original algorithm for the code was used to change skeleton bone rolls to be parent to child.
+//
+// Reference https://github.com/godotengine/godot-proposals/issues/2961
+void BakeReset::_bake_animation_pose(Node *scene, const String &p_bake_anim) {
+ Map<StringName, BakeResetRestBone> r_rest_bones;
+ Vector<Node3D *> r_meshes;
+ List<Node *> queue;
+ queue.push_back(scene);
+ while (!queue.is_empty()) {
+ List<Node *>::Element *E = queue.front();
+ Node *node = E->get();
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node);
+ // Step 1: import scene with animations into the rest bones data structure.
+ _fetch_reset_animation(ap, r_rest_bones, p_bake_anim);
+
+ int child_count = node->get_child_count();
+ for (int i = 0; i < child_count; i++) {
+ queue.push_back(node->get_child(i));
+ }
+ queue.pop_front();
+ }
+
+ queue.push_back(scene);
+ while (!queue.is_empty()) {
+ List<Node *>::Element *E = queue.front();
+ Node *node = E->get();
+ EditorSceneImporterMeshNode3D *editor_mesh_3d = scene->cast_to<EditorSceneImporterMeshNode3D>(node);
+ MeshInstance3D *mesh_3d = scene->cast_to<MeshInstance3D>(node);
+ if (scene->cast_to<Skeleton3D>(node)) {
+ Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(node);
+
+ // Step 2: Bake the RESET animation from the RestBone to the skeleton.
+ _fix_skeleton(skeleton, r_rest_bones);
+ }
+ if (editor_mesh_3d) {
+ NodePath path = editor_mesh_3d->get_skeleton_path();
+ if (!path.is_empty() && editor_mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(editor_mesh_3d->get_node_or_null(path))) {
+ r_meshes.push_back(editor_mesh_3d);
+ }
+ } else if (mesh_3d) {
+ NodePath path = mesh_3d->get_skeleton_path();
+ if (!path.is_empty() && mesh_3d->get_node_or_null(path) && Object::cast_to<Skeleton3D>(mesh_3d->get_node_or_null(path))) {
+ r_meshes.push_back(mesh_3d);
+ }
+ }
+ int child_count = node->get_child_count();
+ for (int i = 0; i < child_count; i++) {
+ queue.push_back(node->get_child(i));
+ }
+ queue.pop_front();
+ }
+
+ queue.push_back(scene);
+ while (!queue.is_empty()) {
+ List<Node *>::Element *E = queue.front();
+ Node *node = E->get();
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(node);
+ if (ap) {
+ // Step 3: Key all RESET animation frames to identity.
+ _align_animations(ap, r_rest_bones);
+ }
+
+ int child_count = node->get_child_count();
+ for (int i = 0; i < child_count; i++) {
+ queue.push_back(node->get_child(i));
+ }
+ queue.pop_front();
+ }
+}
+
+void BakeReset::_align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones) {
+ ERR_FAIL_NULL(p_ap);
+ List<StringName> anim_names;
+ p_ap->get_animation_list(&anim_names);
+ for (List<StringName>::Element *anim_i = anim_names.front(); anim_i; anim_i = anim_i->next()) {
+ Ref<Animation> a = p_ap->get_animation(anim_i->get());
+ ERR_CONTINUE(a.is_null());
+ for (Map<StringName, BakeResetRestBone>::Element *rest_bone_i = r_rest_bones.front(); rest_bone_i; rest_bone_i = rest_bone_i->next()) {
+ int track = a->find_track(NodePath(rest_bone_i->key()));
+ if (track == -1) {
+ continue;
+ }
+ int new_track = a->add_track(Animation::TYPE_TRANSFORM3D);
+ NodePath new_path = NodePath(rest_bone_i->key());
+ BakeResetRestBone rest_bone = rest_bone_i->get();
+ a->track_set_path(new_track, new_path);
+ for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) {
+ Vector3 loc;
+ Quaternion rot;
+ Vector3 scale;
+ Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale);
+ ERR_CONTINUE(err);
+ real_t time = a->track_get_key_time(track, key_i);
+ rot.normalize();
+ loc = loc - rest_bone.loc;
+ rot = rest_bone.rest_delta.get_rotation_quaternion().inverse() * rot;
+ rot.normalize();
+ scale = Vector3(1, 1, 1) - (rest_bone.rest_delta.get_scale() - scale);
+ // Apply the reverse of the rest changes to make the key be close to identity transform.
+ a->transform_track_insert_key(new_track, time, loc, rot, scale);
+ }
+ a->remove_track(track);
+ }
+ }
+}
+
+void BakeReset::_fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim) {
+ ERR_FAIL_NULL(p_ap);
+ List<StringName> anim_names;
+ p_ap->get_animation_list(&anim_names);
+ Node *root = p_ap->get_owner();
+ ERR_FAIL_NULL(root);
+ Ref<Animation> a = p_ap->get_animation(p_bake_anim);
+ ERR_FAIL_NULL(a);
+ for (int32_t track = 0; track < a->get_track_count(); track++) {
+ NodePath path = a->track_get_path(track);
+ String string_path = path;
+ Skeleton3D *skeleton = root->cast_to<Skeleton3D>(root->get_node(string_path.get_slice(":", 0)));
+ if (!skeleton) {
+ continue;
+ }
+ String bone_name = string_path.get_slice(":", 1);
+ for (int key_i = 0; key_i < a->track_get_key_count(track); key_i++) {
+ Vector3 loc;
+ Quaternion rot;
+ Vector3 scale;
+ Error err = a->transform_track_get_key(track, key_i, &loc, &rot, &scale);
+ ERR_CONTINUE(err);
+ rot.normalize();
+ Basis rot_basis = Basis(rot, scale);
+ BakeResetRestBone rest_bone;
+ rest_bone.rest_delta = rot_basis;
+ rest_bone.loc = loc;
+ // Store the animation into the RestBone.
+ r_rest_bones[StringName(String(skeleton->get_owner()->get_path_to(skeleton)) + ":" + bone_name)] = rest_bone;
+ break;
+ }
+ }
+}
+
+void BakeReset::_fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones) {
+ int bone_count = p_skeleton->get_bone_count();
+
+ // First iterate through all the bones and update the RestBone.
+ for (int j = 0; j < bone_count; j++) {
+ StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(j);
+ BakeResetRestBone &rest_bone = r_rest_bones[final_path];
+ rest_bone.rest_local = p_skeleton->get_bone_rest(j);
+ }
+ for (int i = 0; i < bone_count; i++) {
+ int parent_bone = p_skeleton->get_bone_parent(i);
+ String path = p_skeleton->get_owner()->get_path_to(p_skeleton);
+ StringName final_path = String(path) + String(":") + p_skeleton->get_bone_name(parent_bone);
+ if (parent_bone >= 0) {
+ r_rest_bones[path].children.push_back(i);
+ }
+ }
+
+ // When we apply transform to a bone, we also have to move all of its children in the opposite direction.
+ for (int i = 0; i < bone_count; i++) {
+ StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i);
+ r_rest_bones[final_path].rest_local = r_rest_bones[final_path].rest_local * Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc);
+ // Iterate through the children and move in the opposite direction.
+ for (int j = 0; j < r_rest_bones[final_path].children.size(); j++) {
+ int child_index = r_rest_bones[final_path].children[j];
+ StringName children_path = String(p_skeleton->get_name()) + String(":") + p_skeleton->get_bone_name(child_index);
+ r_rest_bones[children_path].rest_local = Transform3D(r_rest_bones[final_path].rest_delta, r_rest_bones[final_path].loc).affine_inverse() * r_rest_bones[children_path].rest_local;
+ }
+ }
+
+ for (int i = 0; i < bone_count; i++) {
+ StringName final_path = String(p_skeleton->get_owner()->get_path_to(p_skeleton)) + String(":") + p_skeleton->get_bone_name(i);
+ ERR_CONTINUE(!r_rest_bones.has(final_path));
+ Transform3D rest_transform = r_rest_bones[final_path].rest_local;
+ p_skeleton->set_bone_rest(i, rest_transform);
+ }
+}
diff --git a/editor/import/editor_importer_bake_reset.h b/editor/import/editor_importer_bake_reset.h
new file mode 100644
index 0000000000..e36ae86181
--- /dev/null
+++ b/editor/import/editor_importer_bake_reset.h
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* editor_importer_bake_reset.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef RESOURCE_IMPORTER_BAKE_RESET_H
+#define RESOURCE_IMPORTER_BAKE_RESET_H
+
+#include "scene/main/node.h"
+
+class Skeleton3D;
+class AnimationPlayer;
+class BakeReset {
+ struct BakeResetRestBone {
+ Transform3D rest_local;
+ Basis rest_delta;
+ Vector3 loc;
+ Vector<int> children;
+ };
+
+public:
+ void _bake_animation_pose(Node *scene, const String &p_bake_anim);
+
+private:
+ void _fix_skeleton(Skeleton3D *p_skeleton, Map<StringName, BakeReset::BakeResetRestBone> &r_rest_bones);
+ void _align_animations(AnimationPlayer *p_ap, const Map<StringName, BakeResetRestBone> &r_rest_bones);
+ void _fetch_reset_animation(AnimationPlayer *p_ap, Map<StringName, BakeResetRestBone> &r_rest_bones, const String &p_bake_anim);
+};
+#endif
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index e9160f0414..1e642462dc 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -32,6 +32,7 @@
#include "core/io/resource_saver.h"
#include "editor/editor_node.h"
+#include "editor/import/editor_importer_bake_reset.h"
#include "editor/import/scene_import_settings.h"
#include "editor/import/scene_importer_mesh_node_3d.h"
#include "scene/3d/area_3d.h"
@@ -1060,6 +1061,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "meshes/lightmap_texel_size", PROPERTY_HINT_RANGE, "0.001,100,0.001"), 0.1));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "skins/use_named_skins"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/import"), true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "animation/bake_reset_animation"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "animation/fps", PROPERTY_HINT_RANGE, "1,120,1"), 15));
r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "import_script/path", PROPERTY_HINT_FILE, script_ext_hint), ""));
@@ -1410,6 +1412,11 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
_pre_fix_node(scene, scene, collision_map);
_post_fix_node(scene, scene, collision_map, scanned_meshes, node_data, material_data, animation_data, fps);
+ bool use_bake_reset_animation = p_options["animation/bake_reset_animation"];
+ if (use_bake_reset_animation) {
+ BakeReset bake_reset;
+ bake_reset._bake_animation_pose(scene, "RESET");
+ }
String root_type = p_options["nodes/root_type"];
root_type = root_type.split(" ")[0]; // full root_type is "ClassName (filename.gd)" for a script global class.
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/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/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index e7d4c40034..f8f5e27397 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -28,16 +28,6 @@ namespace Godot
return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
}
- public static real_t DecTime(real_t value, real_t amount, real_t step)
- {
- real_t sgn = Mathf.Sign(value);
- real_t val = Mathf.Abs(value);
- val -= amount * step;
- if (val < 0)
- val = 0;
- return val * sgn;
- }
-
public static int Hash(object var)
{
return godot_icall_GD_hash(var);
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 219ffd01d3..195d766c1d 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -105,117 +105,114 @@
<constant name="MATH_MOVE_TOWARD" value="29" enum="BuiltinFunc">
Moves the number toward a value, based on the third input.
</constant>
- <constant name="MATH_DECTIME" value="30" enum="BuiltinFunc">
- Return the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code].
- </constant>
- <constant name="MATH_RANDOMIZE" value="31" enum="BuiltinFunc">
+ <constant name="MATH_RANDOMIZE" value="30" enum="BuiltinFunc">
Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time.
</constant>
- <constant name="MATH_RANDI" value="32" enum="BuiltinFunc">
+ <constant name="MATH_RANDI" value="31" enum="BuiltinFunc">
Return a random 32 bits integer value. To obtain a random value between 0 to N (where N is smaller than 2^32 - 1), you can use it with the remainder function.
</constant>
- <constant name="MATH_RANDF" value="33" enum="BuiltinFunc">
+ <constant name="MATH_RANDF" value="32" enum="BuiltinFunc">
Return a random floating-point value between 0 and 1. To obtain a random value between 0 to N, you can use it with multiplication.
</constant>
- <constant name="MATH_RANDF_RANGE" value="34" enum="BuiltinFunc">
+ <constant name="MATH_RANDF_RANGE" value="33" enum="BuiltinFunc">
Return a random floating-point value between the two inputs.
</constant>
- <constant name="MATH_RANDI_RANGE" value="35" enum="BuiltinFunc">
+ <constant name="MATH_RANDI_RANGE" value="34" enum="BuiltinFunc">
Return a random 32-bit integer value between the two inputs.
</constant>
- <constant name="MATH_SEED" value="36" enum="BuiltinFunc">
+ <constant name="MATH_SEED" value="35" enum="BuiltinFunc">
Set the seed for the random number generator.
</constant>
- <constant name="MATH_RANDSEED" value="37" enum="BuiltinFunc">
+ <constant name="MATH_RANDSEED" value="36" enum="BuiltinFunc">
Return a random value from the given seed, along with the new seed.
</constant>
- <constant name="MATH_DEG2RAD" value="38" enum="BuiltinFunc">
+ <constant name="MATH_DEG2RAD" value="37" enum="BuiltinFunc">
Convert the input from degrees to radians.
</constant>
- <constant name="MATH_RAD2DEG" value="39" enum="BuiltinFunc">
+ <constant name="MATH_RAD2DEG" value="38" enum="BuiltinFunc">
Convert the input from radians to degrees.
</constant>
- <constant name="MATH_LINEAR2DB" value="40" enum="BuiltinFunc">
+ <constant name="MATH_LINEAR2DB" value="39" enum="BuiltinFunc">
Convert the input from linear volume to decibel volume.
</constant>
- <constant name="MATH_DB2LINEAR" value="41" enum="BuiltinFunc">
+ <constant name="MATH_DB2LINEAR" value="40" enum="BuiltinFunc">
Convert the input from decibel volume to linear volume.
</constant>
- <constant name="MATH_POLAR2CARTESIAN" value="42" enum="BuiltinFunc">
+ <constant name="MATH_POLAR2CARTESIAN" value="41" enum="BuiltinFunc">
Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (X and Y axis).
</constant>
- <constant name="MATH_CARTESIAN2POLAR" value="43" enum="BuiltinFunc">
+ <constant name="MATH_CARTESIAN2POLAR" value="42" enum="BuiltinFunc">
Converts a 2D point expressed in the cartesian coordinate system (X and Y axis) to the polar coordinate system (a distance from the origin and an angle).
</constant>
- <constant name="MATH_WRAP" value="44" enum="BuiltinFunc">
+ <constant name="MATH_WRAP" value="43" enum="BuiltinFunc">
</constant>
- <constant name="MATH_WRAPF" value="45" enum="BuiltinFunc">
+ <constant name="MATH_WRAPF" value="44" enum="BuiltinFunc">
</constant>
- <constant name="LOGIC_MAX" value="46" enum="BuiltinFunc">
+ <constant name="LOGIC_MAX" value="45" enum="BuiltinFunc">
Return the greater of the two numbers, also known as their maximum.
</constant>
- <constant name="LOGIC_MIN" value="47" enum="BuiltinFunc">
+ <constant name="LOGIC_MIN" value="46" enum="BuiltinFunc">
Return the lesser of the two numbers, also known as their minimum.
</constant>
- <constant name="LOGIC_CLAMP" value="48" enum="BuiltinFunc">
+ <constant name="LOGIC_CLAMP" value="47" enum="BuiltinFunc">
Return the input clamped inside the given range, ensuring the result is never outside it. Equivalent to [code]min(max(input, range_low), range_high)[/code].
</constant>
- <constant name="LOGIC_NEAREST_PO2" value="49" enum="BuiltinFunc">
+ <constant name="LOGIC_NEAREST_PO2" value="48" enum="BuiltinFunc">
Return the nearest power of 2 to the input.
</constant>
- <constant name="OBJ_WEAKREF" value="50" enum="BuiltinFunc">
+ <constant name="OBJ_WEAKREF" value="49" enum="BuiltinFunc">
Create a [WeakRef] from the input.
</constant>
- <constant name="TYPE_CONVERT" value="51" enum="BuiltinFunc">
+ <constant name="TYPE_CONVERT" value="50" enum="BuiltinFunc">
Convert between types.
</constant>
- <constant name="TYPE_OF" value="52" enum="BuiltinFunc">
+ <constant name="TYPE_OF" value="51" enum="BuiltinFunc">
Return the type of the input as an integer. Check [enum Variant.Type] for the integers that might be returned.
</constant>
- <constant name="TYPE_EXISTS" value="53" enum="BuiltinFunc">
+ <constant name="TYPE_EXISTS" value="52" enum="BuiltinFunc">
Checks if a type is registered in the [ClassDB].
</constant>
- <constant name="TEXT_CHAR" value="54" enum="BuiltinFunc">
+ <constant name="TEXT_CHAR" value="53" enum="BuiltinFunc">
Return a character with the given ascii value.
</constant>
- <constant name="TEXT_STR" value="55" enum="BuiltinFunc">
+ <constant name="TEXT_STR" value="54" enum="BuiltinFunc">
Convert the input to a string.
</constant>
- <constant name="TEXT_PRINT" value="56" enum="BuiltinFunc">
+ <constant name="TEXT_PRINT" value="55" enum="BuiltinFunc">
Print the given string to the output window.
</constant>
- <constant name="TEXT_PRINTERR" value="57" enum="BuiltinFunc">
+ <constant name="TEXT_PRINTERR" value="56" enum="BuiltinFunc">
Print the given string to the standard error output.
</constant>
- <constant name="TEXT_PRINTRAW" value="58" enum="BuiltinFunc">
+ <constant name="TEXT_PRINTRAW" value="57" enum="BuiltinFunc">
Print the given string to the standard output, without adding a newline.
</constant>
- <constant name="VAR_TO_STR" value="59" enum="BuiltinFunc">
+ <constant name="VAR_TO_STR" value="58" enum="BuiltinFunc">
Serialize a [Variant] to a string.
</constant>
- <constant name="STR_TO_VAR" value="60" enum="BuiltinFunc">
+ <constant name="STR_TO_VAR" value="59" enum="BuiltinFunc">
Deserialize a [Variant] from a string serialized using [constant VAR_TO_STR].
</constant>
- <constant name="VAR_TO_BYTES" value="61" enum="BuiltinFunc">
+ <constant name="VAR_TO_BYTES" value="60" enum="BuiltinFunc">
Serialize a [Variant] to a [PackedByteArray].
</constant>
- <constant name="BYTES_TO_VAR" value="62" enum="BuiltinFunc">
+ <constant name="BYTES_TO_VAR" value="61" enum="BuiltinFunc">
Deserialize a [Variant] from a [PackedByteArray] serialized using [constant VAR_TO_BYTES].
</constant>
- <constant name="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc">
+ <constant name="MATH_SMOOTHSTEP" value="62" enum="BuiltinFunc">
Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [constant MATH_LERP], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula:
[codeblock]
var t = clamp((weight - from) / (to - from), 0.0, 1.0)
return t * t * (3.0 - 2.0 * t)
[/codeblock]
</constant>
- <constant name="MATH_POSMOD" value="64" enum="BuiltinFunc">
+ <constant name="MATH_POSMOD" value="63" enum="BuiltinFunc">
</constant>
- <constant name="MATH_LERP_ANGLE" value="65" enum="BuiltinFunc">
+ <constant name="MATH_LERP_ANGLE" value="64" enum="BuiltinFunc">
</constant>
- <constant name="TEXT_ORD" value="66" enum="BuiltinFunc">
+ <constant name="TEXT_ORD" value="65" enum="BuiltinFunc">
</constant>
- <constant name="FUNC_MAX" value="67" enum="BuiltinFunc">
+ <constant name="FUNC_MAX" value="66" enum="BuiltinFunc">
Represents the size of the [enum BuiltinFunc] enum.
</constant>
</constants>
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index f17ad62531..c61c3ae272 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -68,7 +68,6 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"inverse_lerp",
"range_lerp",
"move_toward",
- "dectime",
"randomize",
"randi",
"randf",
@@ -206,7 +205,6 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case MATH_INVERSE_LERP:
case MATH_SMOOTHSTEP:
case MATH_MOVE_TOWARD:
- case MATH_DECTIME:
case MATH_WRAP:
case MATH_WRAPF:
case LOGIC_CLAMP:
@@ -349,15 +347,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::FLOAT, "delta");
}
} break;
- case MATH_DECTIME: {
- if (p_idx == 0) {
- return PropertyInfo(Variant::FLOAT, "value");
- } else if (p_idx == 1) {
- return PropertyInfo(Variant::FLOAT, "amount");
- } else {
- return PropertyInfo(Variant::FLOAT, "step");
- }
- } break;
case MATH_RANDOMIZE:
case MATH_RANDI:
case MATH_RANDF: {
@@ -536,10 +525,6 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_RANGE_LERP:
case MATH_SMOOTHSTEP:
case MATH_MOVE_TOWARD:
- case MATH_DECTIME: {
- t = Variant::FLOAT;
-
- } break;
case MATH_RANDOMIZE: {
} break;
case MATH_RANDI: {
@@ -837,12 +822,6 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(2);
*r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
} break;
- case VisualScriptBuiltinFunc::MATH_DECTIME: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::dectime((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
case VisualScriptBuiltinFunc::MATH_RANDOMIZE: {
Math::randomize();
@@ -1239,7 +1218,6 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_INVERSE_LERP);
BIND_ENUM_CONSTANT(MATH_RANGE_LERP);
BIND_ENUM_CONSTANT(MATH_MOVE_TOWARD);
- BIND_ENUM_CONSTANT(MATH_DECTIME);
BIND_ENUM_CONSTANT(MATH_RANDOMIZE);
BIND_ENUM_CONSTANT(MATH_RANDI);
BIND_ENUM_CONSTANT(MATH_RANDF);
@@ -1330,7 +1308,6 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/range_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANGE_LERP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/smoothstep", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SMOOTHSTEP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/move_toward", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_MOVE_TOWARD>);
- VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/randi", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDI>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/randf", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDF>);
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index 7196d4b46a..f59a7a0f0c 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -68,7 +68,6 @@ public:
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
MATH_MOVE_TOWARD,
- MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RANDI,
MATH_RANDF,
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/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 0e55915957..2219437c14 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -483,8 +483,8 @@ void Camera2D::force_update_scroll() {
}
void Camera2D::reset_smoothing() {
- smoothed_camera_pos = camera_pos;
_update_scroll();
+ smoothed_camera_pos = camera_pos;
}
void Camera2D::align() {
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index 3f6e926aa7..250a2311a0 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -982,7 +982,6 @@ void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) {
rp.ext_func = _parse_ext_resources;
rp.sub_func = _parse_sub_resources;
- rp.func = nullptr;
rp.userdata = this;
}
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);