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--doc/classes/VisibleOnScreenNotifier2D.xml1
-rw-r--r--doc/classes/VisibleOnScreenNotifier3D.xml2
-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/viewport.cpp5
-rw-r--r--scene/main/window.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp2
24 files changed, 193 insertions, 56 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/doc/classes/VisibleOnScreenNotifier2D.xml b/doc/classes/VisibleOnScreenNotifier2D.xml
index 32cb191067..c6a7bd5690 100644
--- a/doc/classes/VisibleOnScreenNotifier2D.xml
+++ b/doc/classes/VisibleOnScreenNotifier2D.xml
@@ -6,6 +6,7 @@
<description>
The VisibleOnScreenNotifier2D detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a viewport.
If you want nodes to be disabled automatically when they exit the screen, use [VisibleOnScreenEnabler2D] instead.
+ [b]Note:[/b] VisibleOnScreenNotifier2D uses the render culling code to determine whether it's visible on screen, which also means that its [member CanvasItem.visible] must be [code]true[/code] to work correctly.
</description>
<tutorials>
<link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link>
diff --git a/doc/classes/VisibleOnScreenNotifier3D.xml b/doc/classes/VisibleOnScreenNotifier3D.xml
index 6dec09d03f..aecc3dd0d5 100644
--- a/doc/classes/VisibleOnScreenNotifier3D.xml
+++ b/doc/classes/VisibleOnScreenNotifier3D.xml
@@ -6,7 +6,7 @@
<description>
The VisibleOnScreenNotifier3D detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a [Camera3D]'s view.
If you want nodes to be disabled automatically when they exit the screen, use [VisibleOnScreenEnabler3D] instead.
- [b]Note:[/b] VisibleOnScreenNotifier3D uses an approximate heuristic for performance reasons. It doesn't take walls and other occlusion into account. The heuristic is an implementation detail and may change in future versions. If you need precise visibility checking, use another method such as adding an [Area3D] node as a child of a [Camera3D] node and/or [method Vector3.dot].
+ [b]Note:[/b] VisibleOnScreenNotifier3D uses the render culling code to determine whether it's visible on screen, which also means that its [member Node3D.visible] must be [code]true[/code] to work correctly.
</description>
<tutorials>
</tutorials>
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/viewport.cpp b/scene/main/viewport.cpp
index a1e7555a5d..23b7c072be 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -823,11 +823,12 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
stretch_transform_new.scale(scale);
}
- if (size == p_size && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override) {
+ Size2i new_size = p_size.max(Size2i(2, 2));
+ if (size == new_size && size_allocated == p_allocated && stretch_transform == stretch_transform_new && p_size_2d_override == size_2d_override) {
return;
}
- size = p_size;
+ size = new_size;
size_allocated = p_allocated;
size_2d_override = p_size_2d_override;
stretch_transform = stretch_transform_new;
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;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index aecd0593bc..d251a81427 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -844,7 +844,7 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca
}
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
- ERR_FAIL_COND(p_width < 0 && p_height < 0);
+ ERR_FAIL_COND(p_width < 0 || p_height < 0);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);