summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/input/input.cpp9
-rw-r--r--core/input/input_event.cpp6
-rw-r--r--doc/classes/AnimationTree.xml84
-rw-r--r--doc/classes/ProjectSettings.xml3
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp1
-rw-r--r--editor/editor_autoload_settings.cpp2
-rw-r--r--editor/editor_locale_dialog.cpp6
-rw-r--r--editor/event_listener_line_edit.cpp3
-rw-r--r--editor/import/dynamic_font_import_settings.cpp14
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp2
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp2
-rw-r--r--editor/project_manager.cpp4
-rw-r--r--modules/gdscript/gdscript.cpp1
-rw-r--r--modules/gdscript/gdscript_parser.cpp2
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/animation_tree.cpp73
-rw-r--r--scene/animation/animation_tree.h14
-rw-r--r--scene/animation/root_motion_view.cpp7
-rw-r--r--scene/main/window.cpp2
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;