diff options
-rw-r--r-- | core/input/input.cpp | 9 | ||||
-rw-r--r-- | core/input/input_event.cpp | 6 | ||||
-rw-r--r-- | doc/classes/AnimationTree.xml | 84 | ||||
-rw-r--r-- | doc/classes/ProjectSettings.xml | 3 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 1 | ||||
-rw-r--r-- | editor/editor_autoload_settings.cpp | 2 | ||||
-rw-r--r-- | editor/editor_locale_dialog.cpp | 6 | ||||
-rw-r--r-- | editor/event_listener_line_edit.cpp | 3 | ||||
-rw-r--r-- | editor/import/dynamic_font_import_settings.cpp | 14 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_map_editor.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_set_editor.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/tiles/tiles_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | editor/project_manager.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/gdscript.cpp | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 2 | ||||
-rw-r--r-- | scene/animation/animation_player.cpp | 2 | ||||
-rw-r--r-- | scene/animation/animation_tree.cpp | 73 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 14 | ||||
-rw-r--r-- | scene/animation/root_motion_view.cpp | 7 | ||||
-rw-r--r-- | scene/main/window.cpp | 2 |
20 files changed, 187 insertions, 52 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index 071d9ba648..c04fc894c8 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -231,14 +231,17 @@ Input::VelocityTrack::VelocityTrack() { bool Input::is_anything_pressed() const { _THREAD_SAFE_METHOD_ + if (!keys_pressed.is_empty() || !joy_buttons_pressed.is_empty() || !mouse_button_mask.is_empty()) { + return true; + } + for (const KeyValue<StringName, Input::Action> &E : action_state) { if (E.value.pressed) { return true; } } - return !keys_pressed.is_empty() || - !joy_buttons_pressed.is_empty() || - !mouse_button_mask.is_empty(); + + return false; } bool Input::is_key_pressed(Key p_keycode) const { diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 7c4642a8a5..a6c1bb168c 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -1186,14 +1186,14 @@ static const char *_joy_button_descriptions[(size_t)JoyButton::SDL_MAX] = { }; String InputEventJoypadButton::as_text() const { - String text = "Joypad Button " + itos((int64_t)button_index); + String text = vformat(RTR("Joypad Button %d"), (int64_t)button_index); if (button_index > JoyButton::INVALID && button_index < JoyButton::SDL_MAX) { - text += vformat(" (%s)", _joy_button_descriptions[(size_t)button_index]); + text += vformat(" (%s)", TTRGET(_joy_button_descriptions[(size_t)button_index])); } if (pressure != 0) { - text += ", Pressure:" + String(Variant(pressure)); + text += ", " + RTR("Pressure:") + " " + String(Variant(pressure)); } return text; diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml index 98256f0a38..ed98f47f58 100644 --- a/doc/classes/AnimationTree.xml +++ b/doc/classes/AnimationTree.xml @@ -33,7 +33,7 @@ <method name="get_root_motion_position" qualifiers="const"> <return type="Vector3" /> <description> - Retrieve the motion of position with the [member root_motion_track] as a [Vector3] that can be used elsewhere. + Retrieve the motion delta of position with the [member root_motion_track] as a [Vector3] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_POSITION_3D], returns [code]Vector3(0, 0, 0)[/code]. See also [member root_motion_track] and [RootMotionView]. The most basic example is applying position to [CharacterBody3D]: @@ -50,12 +50,46 @@ move_and_slide() [/gdscript] [/codeblocks] + By using this in combination with [method get_root_motion_position_accumulator], you can apply the root motion position more correctly to account for the rotation of the node. + [codeblocks] + [gdscript] + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + set_quaternion(get_quaternion() * animation_tree.get_root_motion_rotation()) + var velocity: Vector3 = (animation_tree.get_root_motion_rotation_accumulator().inverse() * get_quaternion()) * animation_tree.get_root_motion_position() / delta + set_velocity(velocity) + move_and_slide() + [/gdscript] + [/codeblocks] + </description> + </method> + <method name="get_root_motion_position_accumulator" qualifiers="const"> + <return type="Vector3" /> + <description> + Retrieve the blended value of the position tracks with the [member root_motion_track] as a [Vector3] that can be used elsewhere. + This is useful in cases where you want to respect the initial key values of the animation. + For example, if an animation with only one key [code]Vector3(0, 0, 0)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(1, 0, 1)[/code] is played in the next frame, the difference can be calculated as follows: + [codeblocks] + [gdscript] + var prev_root_motion_position_accumulator: Vector3 + + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + var current_root_motion_position_accumulator: Vector3 = animation_tree.get_root_motion_position_accumulator() + var difference: Vector3 = current_root_motion_position_accumulator - prev_root_motion_position_accumulator + prev_root_motion_position_accumulator = current_root_motion_position_accumulator + transform.origin += difference + [/gdscript] + [/codeblocks] + However, if the animation loops, an unintended discrete change may occur, so this is only useful for some simple use cases. </description> </method> <method name="get_root_motion_rotation" qualifiers="const"> <return type="Quaternion" /> <description> - Retrieve the motion of rotation with the [member root_motion_track] as a [Quaternion] that can be used elsewhere. + Retrieve the motion delta of rotation with the [member root_motion_track] as a [Quaternion] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_ROTATION_3D], returns [code]Quaternion(0, 0, 0, 1)[/code]. See also [member root_motion_track] and [RootMotionView]. The most basic example is applying rotation to [CharacterBody3D]: @@ -69,10 +103,33 @@ [/codeblocks] </description> </method> + <method name="get_root_motion_rotation_accumulator" qualifiers="const"> + <return type="Quaternion" /> + <description> + Retrieve the blended value of the rotation tracks with the [member root_motion_track] as a [Quaternion] that can be used elsewhere. + This is necessary to apply the root motion position correctly, taking rotation into account. See also [method get_root_motion_position]. + Also, this is useful in cases where you want to respect the initial key values of the animation. + For example, if an animation with only one key [code]Quaternion(0, 0, 0, 1)[/code] is played in the previous frame and then an animation with only one key [code]Quaternion(0, 0.707, 0, 0.707)[/code] is played in the next frame, the difference can be calculated as follows: + [codeblocks] + [gdscript] + var prev_root_motion_rotation_accumulator: Quaternion + + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + var current_root_motion_rotation_accumulator: Quaternion = animation_tree.get_root_motion_Quaternion_accumulator() + var difference: Quaternion = prev_root_motion_rotation_accumulator.inverse() * current_root_motion_rotation_accumulator + prev_root_motion_rotation_accumulator = current_root_motion_rotation_accumulator + transform.basis *= difference + [/gdscript] + [/codeblocks] + However, if the animation loops, an unintended discrete change may occur, so this is only useful for some simple use cases. + </description> + </method> <method name="get_root_motion_scale" qualifiers="const"> <return type="Vector3" /> <description> - Retrieve the motion of scale with the [member root_motion_track] as a [Vector3] that can be used elsewhere. + Retrieve the motion delta of scale with the [member root_motion_track] as a [Vector3] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_SCALE_3D], returns [code]Vector3(0, 0, 0)[/code]. See also [member root_motion_track] and [RootMotionView]. The most basic example is applying scale to [CharacterBody3D]: @@ -92,6 +149,27 @@ [/codeblocks] </description> </method> + <method name="get_root_motion_scale_accumulator" qualifiers="const"> + <return type="Vector3" /> + <description> + Retrieve the blended value of the scale tracks with the [member root_motion_track] as a [Vector3] that can be used elsewhere. + For example, if an animation with only one key [code]Vector3(1, 1, 1)[/code] is played in the previous frame and then an animation with only one key [code]Vector3(2, 2, 2)[/code] is played in the next frame, the difference can be calculated as follows: + [codeblocks] + [gdscript] + var prev_root_motion_scale_accumulator: Vector3 + + func _process(delta): + if Input.is_action_just_pressed("animate"): + state_machine.travel("Animate") + var current_root_motion_scale_accumulator: Vector3 = animation_tree.get_root_motion_scale_accumulator() + var difference: Vector3 = current_root_motion_scale_accumulator - prev_root_motion_scale_accumulator + prev_root_motion_scale_accumulator = current_root_motion_scale_accumulator + transform.basis = transform.basis.scaled(difference) + [/gdscript] + [/codeblocks] + However, if the animation loops, an unintended discrete change may occur, so this is only useful for some simple use cases. + </description> + </method> </methods> <members> <member name="active" type="bool" setter="set_active" getter="is_active" default="false"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index c30747eac1..21be5e4bee 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -474,9 +474,6 @@ <member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a static method from an instance of a class instead of from the class directly. </member> - <member name="debug/gdscript/warnings/treat_warnings_as_errors" type="bool" setter="" getter="" default="false"> - If [code]true[/code], all warnings will be reported as if they are errors. - </member> <member name="debug/gdscript/warnings/unassigned_variable" type="int" setter="" getter="" default="1"> When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when using a variable that wasn't previously assigned. </member> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 0e217f699e..3c5441f3c4 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -2259,6 +2259,7 @@ void RasterizerCanvasGLES3::reset_canvas() { glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); glActiveTexture(GL_TEXTURE0 + GLES3::Config::get_singleton()->max_texture_image_units - 2); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index f843733f2c..a6defd0e14 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -890,7 +890,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() { hbc->add_child(autoload_add_path); autoload_add_path->set_h_size_flags(Control::SIZE_EXPAND_FILL); autoload_add_path->set_clear_button_enabled(true); - autoload_add_path->set_placeholder(vformat(TTR(R"(Set path or press "%s" to create a script.)"), TTR("Add"))); + autoload_add_path->set_placeholder(vformat(TTR("Set path or press \"%s\" to create a script."), TTR("Add"))); autoload_add_path->connect("text_changed", callable_mp(this, &EditorAutoloadSettings::_autoload_path_text_changed)); browse_button = memnew(Button); diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp index fbf3c99690..13b4a8c128 100644 --- a/editor/editor_locale_dialog.cpp +++ b/editor/editor_locale_dialog.cpp @@ -294,7 +294,7 @@ void EditorLocaleDialog::_update_tree() { if (!is_edit_mode) { TreeItem *t = script_list->create_item(s_root); - t->set_text(0, "[Default]"); + t->set_text(0, TTR("[Default]")); t->set_metadata(0, ""); } @@ -404,7 +404,7 @@ EditorLocaleDialog::EditorLocaleDialog() { } { edit_filters = memnew(CheckButton); - edit_filters->set_text("Edit Filters"); + edit_filters->set_text(TTR("Edit Filters")); edit_filters->set_toggle_mode(true); edit_filters->set_pressed(false); edit_filters->connect("toggled", callable_mp(this, &EditorLocaleDialog::_edit_filters)); @@ -412,7 +412,7 @@ EditorLocaleDialog::EditorLocaleDialog() { } { advanced = memnew(CheckButton); - advanced->set_text("Advanced"); + advanced->set_text(TTR("Advanced")); advanced->set_toggle_mode(true); advanced->set_pressed(false); advanced->connect("toggled", callable_mp(this, &EditorLocaleDialog::_toggle_advanced)); diff --git a/editor/event_listener_line_edit.cpp b/editor/event_listener_line_edit.cpp index ea4a7133bf..ee401810ad 100644 --- a/editor/event_listener_line_edit.cpp +++ b/editor/event_listener_line_edit.cpp @@ -105,7 +105,8 @@ String EventListenerLineEdit::get_event_text(const Ref<InputEvent> &p_event, boo desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]); } - text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc); + // TRANSLATORS: %d is the axis number, the first %s is either "-" or "+", and the second %s is the description of the axis. + text = vformat(TTR("Joypad Axis %d %s (%s)"), (int64_t)jp_motion->get_axis(), jp_motion->get_axis_value() < 0 ? "-" : "+", desc); } if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) { String device_string = get_device_string(p_event->get_device()); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 6e74c42b2c..b34656c481 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -36,7 +36,9 @@ #include "editor/editor_inspector.h" #include "editor/editor_locale_dialog.h" #include "editor/editor_node.h" +#include "editor/editor_property_name_processor.h" #include "editor/editor_scale.h" +#include "editor/editor_settings.h" /*************************************************************************/ /* Settings data */ @@ -926,6 +928,15 @@ void DynamicFontImportSettings::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { add_var->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); } break; + + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/localize_settings")) { + EditorPropertyNameProcessor::Style style = EditorPropertyNameProcessor::get_singleton()->get_settings_style(); + inspector_general->set_property_name_style(style); + inspector_vars->set_property_name_style(style); + inspector_text->set_property_name_style(style); + } + } break; } } @@ -1334,6 +1345,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { inspector_general->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector_general->set_custom_minimum_size(Size2(300 * EDSCALE, 250 * EDSCALE)); inspector_general->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_main_prop_changed)); + inspector_general->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); page1_hb->add_child(inspector_general); // Page 2 layout: Configurations @@ -1386,6 +1398,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { inspector_vars = memnew(EditorInspector); inspector_vars->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector_vars->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_variation_changed)); + inspector_vars->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); page2_side_vb->add_child(inspector_vars); VBoxContainer *preload_pages_vb = memnew(VBoxContainer); @@ -1461,6 +1474,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { inspector_text->set_v_size_flags(Control::SIZE_EXPAND_FILL); inspector_text->set_custom_minimum_size(Size2(300 * EDSCALE, 250 * EDSCALE)); inspector_text->connect("property_edited", callable_mp(this, &DynamicFontImportSettings::_change_text_opts)); + inspector_text->set_property_name_style(EditorPropertyNameProcessor::get_singleton()->get_settings_style()); page2_1_hb->add_child(inspector_text); text_edit = memnew(TextEdit); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index f0a02a3768..8277e473fd 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -1277,7 +1277,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() { tile_map->set_cell(tile_map_layer, kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile); } - if (EditorNode::get_singleton()->is_resource_read_only(tile_set)) { + if (!EditorNode::get_singleton()->is_resource_read_only(tile_set)) { // Creating a pattern in the pattern list. select_last_pattern = true; int new_pattern_index = tile_set->get_patterns_count(); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 39d17c718e..358cc47977 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -687,7 +687,7 @@ void TileSetEditor::_undo_redo_inspector_callback(Object *p_undo_redo, Object *p void TileSetEditor::edit(Ref<TileSet> p_tile_set) { bool new_read_only_state = false; - if (tile_set.is_valid()) { + if (p_tile_set.is_valid()) { new_read_only_state = EditorNode::get_singleton()->is_resource_read_only(p_tile_set); } diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index fad36660d9..78522dfa73 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -117,7 +117,7 @@ void TilesEditorPlugin::_thread() { tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2); // Add the viewport at the last moment to avoid rendering too early. - EditorNode::get_singleton()->add_child(viewport); + EditorNode::get_singleton()->call_deferred("add_child", viewport); RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<TilesEditorPlugin *>(this), &TilesEditorPlugin::_preview_frame_started), Object::CONNECT_ONE_SHOT); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 105e3a5d47..6c7ad259ea 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -961,8 +961,8 @@ public: default_files_container->add_child(l); vcs_metadata_selection = memnew(OptionButton); vcs_metadata_selection->set_custom_minimum_size(Size2(100, 20)); - vcs_metadata_selection->add_item("None", (int)EditorVCSInterface::VCSMetadata::NONE); - vcs_metadata_selection->add_item("Git", (int)EditorVCSInterface::VCSMetadata::GIT); + vcs_metadata_selection->add_item(TTR("None"), (int)EditorVCSInterface::VCSMetadata::NONE); + vcs_metadata_selection->add_item(TTR("Git"), (int)EditorVCSInterface::VCSMetadata::GIT); vcs_metadata_selection->select((int)EditorVCSInterface::VCSMetadata::GIT); default_files_container->add_child(vcs_metadata_selection); Control *spacer = memnew(Control); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index a876229276..fe79f37454 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -2578,7 +2578,6 @@ GDScriptLanguage::GDScriptLanguage() { #ifdef DEBUG_ENABLED GLOBAL_DEF("debug/gdscript/warnings/enable", true); - GLOBAL_DEF("debug/gdscript/warnings/treat_warnings_as_errors", false); GLOBAL_DEF("debug/gdscript/warnings/exclude_addons", true); for (int i = 0; i < (int)GDScriptWarning::WARNING_MAX; i++) { GDScriptWarning::Code code = (GDScriptWarning::Code)i; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 42e1f27603..b5cb5a4680 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -175,7 +175,7 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_ warning.leftmost_column = p_source->leftmost_column; warning.rightmost_column = p_source->rightmost_column; - if (warn_level == GDScriptWarning::WarnLevel::ERROR || bool(GLOBAL_GET("debug/gdscript/warnings/treat_warnings_as_errors"))) { + if (warn_level == GDScriptWarning::WarnLevel::ERROR) { push_error(warning.get_message() + String(" (Warning treated as error.)"), p_source); return; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index ad0c19b1e6..fc3a3d306f 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -199,7 +199,7 @@ void AnimationPlayer::_validate_property(PropertyInfo &p_property) const { void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const { List<PropertyInfo> anim_names; - anim_names.push_back(PropertyInfo(Variant::DICTIONARY, "libraries")); + anim_names.push_back(PropertyInfo(Variant::DICTIONARY, PNAME("libraries"))); for (const KeyValue<StringName, AnimationData> &E : animation_set) { if (E.value.next != StringName()) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 7c2edef1de..9f9916c1c6 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -567,6 +567,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { List<StringName> sname; player->get_animation_list(&sname); + root_motion_cache.loc = Vector3(0, 0, 0); + root_motion_cache.rot = Quaternion(0, 0, 0, 1); + root_motion_cache.scale = Vector3(1, 1, 1); + Ref<Animation> reset_anim; bool has_reset_anim = player->has_animation(SceneStringNames::get_singleton()->RESET); if (has_reset_anim) { @@ -1035,14 +1039,13 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_POSITION_3D: { TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (track->root_motion) { - t->loc = Vector3(0, 0, 0); - t->rot = Quaternion(0, 0, 0, 1); - t->scale = Vector3(1, 1, 1); - } else { - t->loc = t->init_loc; - t->rot = t->init_rot; - t->scale = t->init_scale; + root_motion_cache.loc = Vector3(0, 0, 0); + root_motion_cache.rot = Quaternion(0, 0, 0, 1); + root_motion_cache.scale = Vector3(1, 1, 1); } + t->loc = t->init_loc; + t->rot = t->init_rot; + t->scale = t->init_scale; } break; case Animation::TYPE_BLEND_SHAPE: { TrackCacheBlendShape *t = static_cast<TrackCacheBlendShape *>(track); @@ -1117,6 +1120,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; // Nothing to blend. } TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); + if (track->root_motion && calc_root) { double prev_time = time - delta; if (!backward) { @@ -1164,7 +1168,7 @@ void AnimationTree::_process_graph(double p_delta) { loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, (double)a->get_length(), &loc[1]); loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); - t->loc += (loc[1] - loc[0]) * blend; + root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = 0; } } else { @@ -1176,7 +1180,7 @@ void AnimationTree::_process_graph(double p_delta) { loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); a->position_track_interpolate(i, 0, &loc[1]); loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); - t->loc += (loc[1] - loc[0]) * blend; + root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = (double)a->get_length(); } } @@ -1186,13 +1190,13 @@ void AnimationTree::_process_graph(double p_delta) { continue; } loc[0] = post_process_key_value(a, i, loc[0], t->object, t->bone_idx); - a->position_track_interpolate(i, time, &loc[1]); loc[1] = post_process_key_value(a, i, loc[1], t->object, t->bone_idx); - t->loc += (loc[1] - loc[0]) * blend; + root_motion_cache.loc += (loc[1] - loc[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); + } - } else { + { Vector3 loc; Error err = a->position_track_interpolate(i, time, &loc); @@ -1211,6 +1215,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; // Nothing to blend. } TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); + if (track->root_motion && calc_root) { double prev_time = time - delta; if (!backward) { @@ -1258,7 +1263,7 @@ void AnimationTree::_process_graph(double p_delta) { rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]); rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx); - t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); + root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = 0; } } else { @@ -1269,7 +1274,7 @@ void AnimationTree::_process_graph(double p_delta) { } rot[0] = post_process_key_value(a, i, rot[0], t->object, t->bone_idx); a->rotation_track_interpolate(i, 0, &rot[1]); - t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); + root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = (double)a->get_length(); } } @@ -1282,10 +1287,11 @@ void AnimationTree::_process_graph(double p_delta) { a->rotation_track_interpolate(i, time, &rot[1]); rot[1] = post_process_key_value(a, i, rot[1], t->object, t->bone_idx); - t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); + root_motion_cache.rot = (root_motion_cache.rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized(); prev_time = !backward ? 0 : (double)a->get_length(); + } - } else { + { Quaternion rot; Error err = a->rotation_track_interpolate(i, time, &rot); @@ -1304,6 +1310,7 @@ void AnimationTree::_process_graph(double p_delta) { continue; // Nothing to blend. } TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); + if (track->root_motion && calc_root) { double prev_time = time - delta; if (!backward) { @@ -1350,7 +1357,7 @@ void AnimationTree::_process_graph(double p_delta) { } scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, (double)a->get_length(), &scale[1]); - t->scale += (scale[1] - scale[0]) * blend; + root_motion_cache.scale += (scale[1] - scale[0]) * blend; scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); prev_time = 0; } @@ -1363,7 +1370,7 @@ void AnimationTree::_process_graph(double p_delta) { scale[0] = post_process_key_value(a, i, scale[0], t->object, t->bone_idx); a->scale_track_interpolate(i, 0, &scale[1]); scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); - t->scale += (scale[1] - scale[0]) * blend; + root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = (double)a->get_length(); } } @@ -1376,10 +1383,11 @@ void AnimationTree::_process_graph(double p_delta) { a->scale_track_interpolate(i, time, &scale[1]); scale[1] = post_process_key_value(a, i, scale[1], t->object, t->bone_idx); - t->scale += (scale[1] - scale[0]) * blend; + root_motion_cache.scale += (scale[1] - scale[0]) * blend; prev_time = !backward ? 0 : (double)a->get_length(); + } - } else { + { Vector3 scale; Error err = a->scale_track_interpolate(i, time, &scale); @@ -1692,10 +1700,12 @@ void AnimationTree::_process_graph(double p_delta) { TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track); if (t->root_motion) { - root_motion_position = t->loc; - root_motion_rotation = t->rot; - root_motion_scale = t->scale - Vector3(1, 1, 1); - + root_motion_position = root_motion_cache.loc; + root_motion_rotation = root_motion_cache.rot; + root_motion_scale = root_motion_cache.scale - Vector3(1, 1, 1); + root_motion_position_accumulator = t->loc; + root_motion_rotation_accumulator = t->rot; + root_motion_scale_accumulator = t->scale; } else if (t->skeleton && t->bone_idx >= 0) { if (t->loc_used) { t->skeleton->set_bone_pose_position(t->bone_idx, t->loc); @@ -1997,6 +2007,18 @@ Vector3 AnimationTree::get_root_motion_scale() const { return root_motion_scale; } +Vector3 AnimationTree::get_root_motion_position_accumulator() const { + return root_motion_position_accumulator; +} + +Quaternion AnimationTree::get_root_motion_rotation_accumulator() const { + return root_motion_rotation_accumulator; +} + +Vector3 AnimationTree::get_root_motion_scale_accumulator() const { + return root_motion_scale_accumulator; +} + void AnimationTree::_tree_changed() { if (properties_dirty) { return; @@ -2186,6 +2208,9 @@ void AnimationTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_root_motion_position"), &AnimationTree::get_root_motion_position); ClassDB::bind_method(D_METHOD("get_root_motion_rotation"), &AnimationTree::get_root_motion_rotation); ClassDB::bind_method(D_METHOD("get_root_motion_scale"), &AnimationTree::get_root_motion_scale); + ClassDB::bind_method(D_METHOD("get_root_motion_position_accumulator"), &AnimationTree::get_root_motion_position_accumulator); + ClassDB::bind_method(D_METHOD("get_root_motion_rotation_accumulator"), &AnimationTree::get_root_motion_rotation_accumulator); + ClassDB::bind_method(D_METHOD("get_root_motion_scale_accumulator"), &AnimationTree::get_root_motion_scale_accumulator); ClassDB::bind_method(D_METHOD("_update_properties"), &AnimationTree::_update_properties); diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 0540add85b..c68cae56ea 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -228,6 +228,12 @@ private: } }; + struct RootMotionCache { + Vector3 loc = Vector3(0, 0, 0); + Quaternion rot = Quaternion(0, 0, 0, 1); + Vector3 scale = Vector3(1, 1, 1); + }; + struct TrackCacheBlendShape : public TrackCache { MeshInstance3D *mesh_3d = nullptr; float init_value = 0; @@ -294,6 +300,7 @@ private: } }; + RootMotionCache root_motion_cache; HashMap<NodePath, TrackCache *> track_cache; HashSet<TrackCache *> playing_caches; Vector<Node *> playing_audio_stream_players; @@ -327,6 +334,9 @@ private: Vector3 root_motion_position = Vector3(0, 0, 0); Quaternion root_motion_rotation = Quaternion(0, 0, 0, 1); Vector3 root_motion_scale = Vector3(0, 0, 0); + Vector3 root_motion_position_accumulator = Vector3(0, 0, 0); + Quaternion root_motion_rotation_accumulator = Quaternion(0, 0, 0, 1); + Vector3 root_motion_scale_accumulator = Vector3(1, 1, 1); friend class AnimationNode; bool properties_dirty = true; @@ -394,6 +404,10 @@ public: Quaternion get_root_motion_rotation() const; Vector3 get_root_motion_scale() const; + Vector3 get_root_motion_position_accumulator() const; + Quaternion get_root_motion_rotation_accumulator() const; + Vector3 get_root_motion_scale_accumulator() const; + real_t get_connection_activity(const StringName &p_path, int p_connection) const; void advance(double p_time); diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index 3d8d451c70..fc758b9456 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -88,6 +88,7 @@ void RootMotionView::_notification(int p_what) { case NOTIFICATION_INTERNAL_PROCESS: case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { Transform3D transform; + Basis diff; if (has_node(path)) { Node *node = get_node(path); @@ -103,9 +104,9 @@ void RootMotionView::_notification(int p_what) { set_process_internal(true); set_physics_process_internal(false); } - transform.origin = tree->get_root_motion_position(); transform.basis = tree->get_root_motion_rotation(); // Scale is meaningless. + diff = tree->get_root_motion_rotation_accumulator(); } } @@ -115,8 +116,10 @@ void RootMotionView::_notification(int p_what) { first = false; - accumulated.origin += transform.origin; accumulated.basis *= transform.basis; + transform.origin = (diff.inverse() * accumulated.basis).xform(transform.origin); + accumulated.origin += transform.origin; + accumulated.origin.x = Math::fposmod(accumulated.origin.x, cell_size); if (zero_y) { accumulated.origin.y = 0; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 44df648552..771e074d48 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1462,7 +1462,7 @@ void Window::popup_centered(const Size2i &p_minsize) { } Rect2i popup_rect; - popup_rect.size = _clamp_window_size(p_minsize); + popup_rect.size = _clamp_window_size(get_size().max(p_minsize)); if (parent_rect != Rect2()) { popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2; |