summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/static_checks.yml4
-rw-r--r--core/io/image.cpp2
-rw-r--r--core/math/quaternion.cpp9
-rw-r--r--core/math/quaternion.h3
-rw-r--r--core/math/vector3.h27
-rw-r--r--core/variant/variant_call.cpp4
-rw-r--r--doc/classes/Animation.xml15
-rw-r--r--doc/classes/CanvasItem.xml6
-rw-r--r--doc/classes/DisplayServer.xml2
-rw-r--r--doc/classes/Font.xml25
-rw-r--r--doc/classes/Quaternion.xml10
-rw-r--r--doc/classes/Vector3.xml11
-rw-r--r--editor/action_map_editor.cpp10
-rw-r--r--editor/animation_track_editor.cpp177
-rw-r--r--editor/animation_track_editor.h4
-rw-r--r--editor/animation_track_editor_plugins.cpp4
-rw-r--r--editor/editor_fonts.cpp15
-rw-r--r--editor/editor_properties.cpp3
-rw-r--r--editor/icons/NewKey.svg1
-rw-r--r--editor/import/resource_importer_scene.cpp29
-rw-r--r--editor/import/resource_importer_scene.h1
-rw-r--r--editor/inspector_dock.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp6
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp59
-rw-r--r--editor/plugins/node_3d_editor_plugin.h6
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp268
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h38
-rw-r--r--editor/plugins/theme_editor_preview.cpp5
-rw-r--r--editor/plugins/theme_editor_preview.h1
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp15
-rw-r--r--editor/translations/ar.po8
-rw-r--r--editor/translations/ca.po135
-rw-r--r--editor/translations/de.po42
-rw-r--r--editor/translations/es.po47
-rw-r--r--editor/translations/es_AR.po267
-rw-r--r--editor/translations/fa.po36
-rw-r--r--editor/translations/fi.po36
-rw-r--r--editor/translations/fr.po154
-rw-r--r--editor/translations/he.po6
-rw-r--r--editor/translations/ja.po132
-rw-r--r--editor/translations/pt.po90
-rw-r--r--editor/translations/pt_BR.po144
-rw-r--r--editor/translations/ru.po44
-rw-r--r--editor/translations/sv.po11
-rw-r--r--editor/translations/uk.po36
-rw-r--r--editor/translations/zh_CN.po38
-rw-r--r--methods.py4
-rwxr-xr-xmisc/hooks/pre-commit-clang-format4
-rwxr-xr-xmisc/scripts/clang_format.sh2
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/mono/csharp_script.cpp16
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/text_server_adv/text_server_adv.cpp1
-rw-r--r--modules/text_server_fb/text_server_fb.cpp1
-rw-r--r--platform/android/java/build.gradle14
-rw-r--r--platform/linuxbsd/display_server_x11.cpp1
-rw-r--r--scene/2d/collision_polygon_2d.cpp1
-rw-r--r--scene/2d/collision_shape_2d.cpp2
-rw-r--r--scene/2d/ray_cast_2d.cpp1
-rw-r--r--scene/3d/cpu_particles_3d.cpp1
-rw-r--r--scene/3d/skeleton_3d.cpp22
-rw-r--r--scene/gui/code_edit.cpp2
-rw-r--r--scene/gui/control.cpp28
-rw-r--r--scene/gui/line_edit.cpp8
-rw-r--r--scene/gui/rich_text_label.cpp6
-rw-r--r--scene/gui/text_edit.cpp16
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--scene/main/canvas_item.cpp6
-rw-r--r--scene/main/canvas_item.h8
-rw-r--r--scene/resources/animation.cpp1653
-rw-r--r--scene/resources/animation.h95
-rw-r--r--scene/resources/default_theme/default_theme.cpp1
-rw-r--r--scene/resources/font.cpp98
-rw-r--r--scene/resources/font.h28
-rw-r--r--scene/resources/theme.cpp4
-rw-r--r--servers/display_server.cpp1
-rw-r--r--servers/display_server.h1
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl10
-rw-r--r--servers/rendering/renderer_scene_cull.cpp4
80 files changed, 2954 insertions, 1092 deletions
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index fd2e748076..f60046e0dd 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -22,9 +22,9 @@ jobs:
- name: Install dependencies
run: |
- sudo apt-get install -qq dos2unix recode clang-format-11
+ sudo apt-get install -qq dos2unix recode clang-format-12
sudo update-alternatives --remove-all clang-format
- sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-11 100
+ sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-12 100
sudo pip3 install black==20.8b1 pygments
- name: File formatting checks (file_format.sh)
diff --git a/core/io/image.cpp b/core/io/image.cpp
index c70f4b86bd..b82e6637b4 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -797,7 +797,7 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict
uint32_t interp_down = p01 + (((p11 - p01) * src_xofs_frac) >> FRAC_BITS);
uint32_t interp = interp_up + (((interp_down - interp_up) * src_yofs_frac) >> FRAC_BITS);
interp >>= FRAC_BITS;
- p_dst[i * p_dst_width * CC + j * CC + l] = interp;
+ p_dst[i * p_dst_width * CC + j * CC + l] = uint8_t(interp);
} else if (sizeof(T) == 2) { //half float
float xofs_frac = float(src_xofs_frac) / (1 << FRAC_BITS);
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index 3f1d2c58e5..a29a70c1f0 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -189,6 +189,15 @@ Quaternion::operator String() const {
return "(" + String::num_real(x, false) + ", " + String::num_real(y, false) + ", " + String::num_real(z, false) + ", " + String::num_real(w, false) + ")";
}
+Vector3 Quaternion::get_axis() const {
+ real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
+ return Vector3(x * r, y * r, z * r);
+}
+
+float Quaternion::get_angle() const {
+ return 2 * Math::acos(w);
+}
+
Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) {
#ifdef MATH_CHECKS
ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized.");
diff --git a/core/math/quaternion.h b/core/math/quaternion.h
index 35324323b3..e20ea74eb4 100644
--- a/core/math/quaternion.h
+++ b/core/math/quaternion.h
@@ -72,6 +72,9 @@ public:
Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const;
Quaternion cubic_slerp(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const;
+ Vector3 get_axis() const;
+ float get_angle() const;
+
_FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = 2 * Math::acos(w);
real_t r = ((real_t)1) / Math::sqrt(1 - w * w);
diff --git a/core/math/vector3.h b/core/math/vector3.h
index e65ac31c02..dc9aa60458 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -32,9 +32,9 @@
#define VECTOR3_H
#include "core/math/math_funcs.h"
+#include "core/math/vector2.h"
#include "core/math/vector3i.h"
#include "core/string/ustring.h"
-
class Basis;
struct Vector3 {
@@ -103,6 +103,31 @@ struct Vector3 {
Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
+ _FORCE_INLINE_ Vector2 octahedron_encode() const {
+ Vector3 n = *this;
+ n /= Math::abs(n.x) + Math::abs(n.y) + Math::abs(n.z);
+ Vector2 o;
+ if (n.z >= 0.0) {
+ o.x = n.x;
+ o.y = n.y;
+ } else {
+ o.x = (1.0 - Math::abs(n.y)) * (n.x >= 0.0 ? 1.0 : -1.0);
+ o.y = (1.0 - Math::abs(n.x)) * (n.y >= 0.0 ? 1.0 : -1.0);
+ }
+ o.x = o.x * 0.5 + 0.5;
+ o.y = o.y * 0.5 + 0.5;
+ return o;
+ }
+
+ static _FORCE_INLINE_ Vector3 octahedron_decode(const Vector2 &p_oct) {
+ Vector2 f(p_oct.x * 2.0 - 1.0, p_oct.y * 2.0 - 1.0);
+ Vector3 n(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y));
+ float t = CLAMP(-n.z, 0.0, 1.0);
+ n.x += n.x >= 0 ? -t : t;
+ n.y += n.y >= 0 ? -t : t;
+ return n.normalized();
+ }
+
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_b) const;
Basis outer(const Vector3 &p_b) const;
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 6284caae2d..8432ccce85 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1581,6 +1581,8 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, bounce, sarray("n"), varray());
bind_method(Vector3, reflect, sarray("n"), varray());
bind_method(Vector3, sign, sarray(), varray());
+ bind_method(Vector3, octahedron_encode, sarray(), varray());
+ bind_static_method(Vector3, octahedron_decode, sarray("uv"), varray());
/* Vector3i */
@@ -1617,6 +1619,8 @@ static void _register_variant_builtin_methods() {
bind_method(Quaternion, slerpni, sarray("to", "weight"), varray());
bind_method(Quaternion, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray());
bind_method(Quaternion, get_euler, sarray(), varray());
+ bind_method(Quaternion, get_axis, sarray(), varray());
+ bind_method(Quaternion, get_angle, sarray(), varray());
/* Color */
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index ebcced7dc4..e3bb60f6de 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -215,6 +215,14 @@
Clear the animation (clear all tracks and reset all).
</description>
</method>
+ <method name="compress">
+ <return type="void" />
+ <argument index="0" name="page_size" type="int" default="8192" />
+ <argument index="1" name="fps" type="int" default="120" />
+ <argument index="2" name="split_tolerance" type="float" default="4.0" />
+ <description>
+ </description>
+ </method>
<method name="copy_track">
<return type="void" />
<argument index="0" name="track_idx" type="int" />
@@ -226,6 +234,7 @@
<method name="find_track" qualifiers="const">
<return type="int" />
<argument index="0" name="path" type="NodePath" />
+ <argument index="1" name="type" type="int" enum="Animation.TrackType" />
<description>
Returns the index of the specified track. If the track is not found, return -1.
</description>
@@ -370,6 +379,12 @@
Insert a generic key in a given track.
</description>
</method>
+ <method name="track_is_compressed" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="track_idx" type="int" />
+ <description>
+ </description>
+ </method>
<method name="track_is_enabled" qualifiers="const">
<return type="bool" />
<argument index="0" name="track_idx" type="int" />
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 738594ea5d..7be18c1d5c 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -53,7 +53,7 @@
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="String" />
<argument index="3" name="next" type="String" default="&quot;&quot;" />
- <argument index="4" name="size" type="int" default="-1" />
+ <argument index="4" name="size" type="int" default="16" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="6" name="outline_size" type="int" default="0" />
<argument index="7" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -146,7 +146,7 @@
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="max_lines" type="int" default="-1" />
- <argument index="6" name="size" type="int" default="-1" />
+ <argument index="6" name="size" type="int" default="16" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -238,7 +238,7 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
- <argument index="5" name="size" type="int" default="-1" />
+ <argument index="5" name="size" type="int" default="16" />
<argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="7" name="outline_size" type="int" default="0" />
<argument index="8" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 4b43286594..92d6a220d2 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -819,6 +819,8 @@
</constant>
<constant name="FEATURE_SWAP_BUFFERS" value="17" enum="Feature">
</constant>
+ <constant name="FEATURE_CLIPBOARD_PRIMARY" value="19" enum="Feature">
+ </constant>
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
Makes the mouse cursor visible if it is hidden.
</constant>
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index 39881e9eb7..01bc2837f1 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -82,7 +82,7 @@
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="int" />
<argument index="3" name="next" type="int" default="0" />
- <argument index="4" name="size" type="int" default="-1" />
+ <argument index="4" name="size" type="int" default="16" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="6" name="outline_size" type="int" default="0" />
<argument index="7" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -99,7 +99,7 @@
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="max_lines" type="int" default="-1" />
- <argument index="6" name="size" type="int" default="-1" />
+ <argument index="6" name="size" type="int" default="16" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -116,7 +116,7 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
- <argument index="5" name="size" type="int" default="-1" />
+ <argument index="5" name="size" type="int" default="16" />
<argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="7" name="outline_size" type="int" default="0" />
<argument index="8" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -128,7 +128,7 @@
</method>
<method name="get_ascent" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="-1" />
+ <argument index="0" name="size" type="int" default="16" />
<description>
Returns the average font ascent (number of pixels above the baseline).
[b]Note:[/b] Real ascent of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the ascent of empty line).
@@ -138,7 +138,7 @@
<return type="Vector2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
- <argument index="2" name="size" type="int" default="-1" />
+ <argument index="2" name="size" type="int" default="16" />
<description>
Returns the size of a character, optionally taking kerning into account if the next character is provided.
[b]Note:[/b] Do not use this function to calculate width of the string character by character, use [method get_string_size] or [TextLine] instead. The height returned is the font height (see also [method get_height]) and has no relation to the glyph height.
@@ -166,7 +166,7 @@
</method>
<method name="get_descent" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="-1" />
+ <argument index="0" name="size" type="int" default="16" />
<description>
Returns the average font descent (number of pixels below the baseline).
[b]Note:[/b] Real descent of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the descent of empty line).
@@ -174,7 +174,7 @@
</method>
<method name="get_height" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="-1" />
+ <argument index="0" name="size" type="int" default="16" />
<description>
Returns the total average font height (ascent plus descent) in pixels.
[b]Note:[/b] Real height of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate (e.g. as the height of empty line).
@@ -184,7 +184,7 @@
<return type="Vector2" />
<argument index="0" name="text" type="String" />
<argument index="1" name="width" type="float" default="-1" />
- <argument index="2" name="size" type="int" default="-1" />
+ <argument index="2" name="size" type="int" default="16" />
<argument index="3" name="flags" type="int" default="96" />
<description>
Returns the size of a bounding box of a string broken into the lines, taking kerning and advance into account.
@@ -201,7 +201,7 @@
<method name="get_string_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="text" type="String" />
- <argument index="1" name="size" type="int" default="-1" />
+ <argument index="1" name="size" type="int" default="16" />
<argument index="2" name="align" type="int" enum="HAlign" default="0" />
<argument index="3" name="width" type="float" default="-1" />
<argument index="4" name="flags" type="int" default="3" />
@@ -220,7 +220,7 @@
</method>
<method name="get_underline_position" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="-1" />
+ <argument index="0" name="size" type="int" default="16" />
<description>
Return average pixel offset of the underline below the baseline.
[b]Note:[/b] Real underline position of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate.
@@ -228,7 +228,7 @@
</method>
<method name="get_underline_thickness" qualifiers="const">
<return type="float" />
- <argument index="0" name="size" type="int" default="-1" />
+ <argument index="0" name="size" type="int" default="16" />
<description>
Return average thickness of the underline.
[b]Note:[/b] Real underline thickness of the string is context-dependent and can be significantly different from the value returned by this function. Use it only as rough estimate.
@@ -272,9 +272,6 @@
</method>
</methods>
<members>
- <member name="base_size" type="int" setter="set_base_size" getter="get_base_size" default="16">
- Default font size.
- </member>
<member name="spacing_bottom" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the bottom of the line in pixels.
</member>
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
index 7858ac732b..1ef6320d61 100644
--- a/doc/classes/Quaternion.xml
+++ b/doc/classes/Quaternion.xml
@@ -90,6 +90,16 @@
Returns the dot product of two quaternions.
</description>
</method>
+ <method name="get_angle" qualifiers="const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="get_axis" qualifiers="const">
+ <return type="Vector3" />
+ <description>
+ </description>
+ </method>
<method name="get_euler" qualifiers="const">
<return type="Vector3" />
<description>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 267a0d2e9e..078ba1e1a4 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -208,6 +208,17 @@
Returns the vector scaled to unit length. Equivalent to [code]v / v.length()[/code].
</description>
</method>
+ <method name="octahedron_decode" qualifiers="static">
+ <return type="Vector3" />
+ <argument index="0" name="uv" type="Vector2" />
+ <description>
+ </description>
+ </method>
+ <method name="octahedron_encode" qualifiers="const">
+ <return type="Vector2" />
+ <description>
+ </description>
+ </method>
<method name="operator !=" qualifiers="operator">
<return type="bool" />
<description>
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 363d542fd5..fc7e7389d5 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -571,7 +571,13 @@ void InputEventConfigurationDialog::popup_and_configure(const Ref<InputEvent> &p
for (int i = 0; i < MOD_MAX; i++) {
mod_checkboxes[i]->set_pressed(false);
}
- physical_key_checkbox->set_pressed(false);
+
+ // Enable the Physical Key checkbox by default to encourage its use.
+ // Physical Key should be used for most game inputs as it allows keys to work
+ // on non-QWERTY layouts out of the box.
+ // This is especially important for WASD movement layouts.
+ physical_key_checkbox->set_pressed(true);
+
store_command_checkbox->set_pressed(true);
_set_current_device(0);
@@ -702,7 +708,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
physical_key_checkbox = memnew(CheckBox);
physical_key_checkbox->set_text(TTR("Use Physical Keycode"));
- physical_key_checkbox->set_tooltip(TTR("Stores the physical position of the key on the keyboard rather than the keys value. Used for compatibility with non-latin layouts."));
+ physical_key_checkbox->set_tooltip(TTR("Stores the physical position of the key on the keyboard rather than the key's value. Used for compatibility with non-latin layouts.\nThis should generally be enabled for most game shortcuts, but not in non-game applications."));
physical_key_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_physical_keycode_toggled));
physical_key_checkbox->hide();
additional_options_container->add_child(physical_key_checkbox);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 7f118532c9..a85a4450a6 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -584,7 +584,8 @@ public:
} break;
case Animation::TYPE_METHOD: {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
- p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,5,1"));
+ static_assert(VARIANT_ARG_MAX == 8, "PROPERTY_HINT_RANGE needs to be updated if VARIANT_ARG_MAX != 8");
+ p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,8,1"));
Dictionary d = animation->track_get_key_value(track, key);
ERR_FAIL_COND(!d.has("args"));
@@ -1247,7 +1248,8 @@ public:
} break;
case Animation::TYPE_METHOD: {
p_list->push_back(PropertyInfo(Variant::STRING_NAME, "name"));
- p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,5,1"));
+ static_assert(VARIANT_ARG_MAX == 8, "PROPERTY_HINT_RANGE needs to be updated if VARIANT_ARG_MAX != 8");
+ p_list->push_back(PropertyInfo(Variant::INT, "arg_count", PROPERTY_HINT_RANGE, "0,8,1"));
Dictionary d = animation->track_get_key_value(first_track, first_key);
ERR_FAIL_COND(!d.has("args"));
@@ -2037,7 +2039,7 @@ void AnimationTrackEdit::_notification(int p_what) {
update_mode_rect.position.y = int(get_size().height - update_icon->get_height()) / 2;
update_mode_rect.size = update_icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
+ if (!animation->track_is_compressed(track) && animation->track_get_type(track) == Animation::TYPE_VALUE) {
draw_texture(update_icon, update_mode_rect.position);
}
// Make it easier to click.
@@ -2079,7 +2081,7 @@ void AnimationTrackEdit::_notification(int p_what) {
interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
interp_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(icon, interp_mode_rect.position);
}
// Make it easier to click.
@@ -2089,7 +2091,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
interp_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2112,7 +2114,7 @@ void AnimationTrackEdit::_notification(int p_what) {
loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
loop_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2122,7 +2124,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (!animation->track_is_compressed(track) && (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D)) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
loop_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2137,7 +2139,7 @@ void AnimationTrackEdit::_notification(int p_what) {
{
// Erase.
- Ref<Texture2D> icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
+ Ref<Texture2D> icon = get_theme_icon(animation->track_is_compressed(track) ? SNAME("Lock") : SNAME("Remove"), SNAME("EditorIcons"));
remove_rect.position.x = ofs + ((get_size().width - ofs) - icon->get_width()) / 2;
remove_rect.position.y = int(get_size().height - icon->get_height()) / 2;
@@ -2709,60 +2711,63 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
// Check keyframes.
- float scale = timeline->get_zoom_scale();
- int limit = timeline->get_name_limit();
- int limit_end = get_size().width - timeline->get_buttons_width();
- // Left Border including space occupied by keyframes on t=0.
- int limit_start_hitbox = limit - type_icon->get_width();
-
- if (pos.x >= limit_start_hitbox && pos.x <= limit_end) {
- int key_idx = -1;
- float key_distance = 1e20;
+ if (!animation->track_is_compressed(track)) { // Selecting compressed keyframes for editing is not possible.
- // Select should happen in the opposite order of drawing for more accurate overlap select.
- for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
- Rect2 rect = get_key_rect(i, scale);
- float offset = animation->track_get_key_time(track, i) - timeline->get_value();
- offset = offset * scale + limit;
- rect.position.x += offset;
-
- if (rect.has_point(pos)) {
- if (is_key_selectable_by_distance()) {
- float distance = ABS(offset - pos.x);
- if (key_idx == -1 || distance < key_distance) {
+ float scale = timeline->get_zoom_scale();
+ int limit = timeline->get_name_limit();
+ int limit_end = get_size().width - timeline->get_buttons_width();
+ // Left Border including space occupied by keyframes on t=0.
+ int limit_start_hitbox = limit - type_icon->get_width();
+
+ if (pos.x >= limit_start_hitbox && pos.x <= limit_end) {
+ int key_idx = -1;
+ float key_distance = 1e20;
+
+ // Select should happen in the opposite order of drawing for more accurate overlap select.
+ for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
+ Rect2 rect = get_key_rect(i, scale);
+ float offset = animation->track_get_key_time(track, i) - timeline->get_value();
+ offset = offset * scale + limit;
+ rect.position.x += offset;
+
+ if (rect.has_point(pos)) {
+ if (is_key_selectable_by_distance()) {
+ float distance = ABS(offset - pos.x);
+ if (key_idx == -1 || distance < key_distance) {
+ key_idx = i;
+ key_distance = distance;
+ }
+ } else {
+ // First one does it.
key_idx = i;
- key_distance = distance;
+ break;
}
- } else {
- // First one does it.
- key_idx = i;
- break;
}
}
- }
- if (key_idx != -1) {
- if (mb->is_command_pressed() || mb->is_shift_pressed()) {
- if (editor->is_key_selected(track, key_idx)) {
- emit_signal(SNAME("deselect_key"), key_idx);
+ if (key_idx != -1) {
+ if (mb->is_command_pressed() || mb->is_shift_pressed()) {
+ if (editor->is_key_selected(track, key_idx)) {
+ emit_signal(SNAME("deselect_key"), key_idx);
+ } else {
+ emit_signal(SNAME("select_key"), key_idx, false);
+ moving_selection_attempt = true;
+ select_single_attempt = -1;
+ moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
+ }
} else {
- emit_signal(SNAME("select_key"), key_idx, false);
+ if (!editor->is_key_selected(track, key_idx)) {
+ emit_signal(SNAME("select_key"), key_idx, true);
+ select_single_attempt = -1;
+ } else {
+ select_single_attempt = key_idx;
+ }
+
moving_selection_attempt = true;
- select_single_attempt = -1;
moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
}
- } else {
- if (!editor->is_key_selected(track, key_idx)) {
- emit_signal(SNAME("select_key"), key_idx, true);
- select_single_attempt = -1;
- } else {
- select_single_attempt = key_idx;
- }
-
- moving_selection_attempt = true;
- moving_selection_from_ofs = (mb->get_position().x - limit) / timeline->get_zoom_scale();
+ accept_event();
}
- accept_event();
}
}
}
@@ -2994,6 +2999,9 @@ void AnimationTrackEdit::set_in_group(bool p_enable) {
}
void AnimationTrackEdit::append_to_selection(const Rect2 &p_box, bool p_deselection) {
+ if (animation->track_is_compressed(track)) {
+ return; // Compressed keyframes can't be edited
+ }
// Left Border including space occupied by keyframes on t=0.
int limit_start_hitbox = timeline->get_name_limit() - type_icon->get_width();
Rect2 select_rect(limit_start_hitbox, 0, get_size().width - timeline->get_name_limit() - timeline->get_buttons_width(), get_size().height);
@@ -3337,6 +3345,10 @@ void AnimationTrackEditor::_timeline_changed(float p_new_pos, bool p_drag, bool
}
void AnimationTrackEditor::_track_remove_request(int p_track) {
+ if (animation->track_is_compressed(p_track)) {
+ EditorNode::get_singleton()->show_warning(TTR("Compressed tracks can't be edited or removed. Re-import the animation with compression disabled in order to edit."));
+ return;
+ }
int idx = p_track;
if (idx >= 0 && idx < animation->get_track_count()) {
undo_redo->create_action(TTR("Remove Anim Track"));
@@ -3487,7 +3499,7 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
for (const InsertData &E : insert_data) {
// Prevent insertion of multiple tracks.
- if (E.path == p_id.path) {
+ if (E.path == p_id.path && E.type == p_id.type) {
return; // Already inserted a track this frame.
}
}
@@ -3537,7 +3549,11 @@ void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_bezi
}
}
-void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform) {
+void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type, const Variant p_value) {
+ ERR_FAIL_COND(!root);
+ ERR_FAIL_COND_MSG(
+ (p_type != Animation::TYPE_POSITION_3D && p_type != Animation::TYPE_ROTATION_3D && p_type != Animation::TYPE_SCALE_3D),
+ "Track type must be Position/Rotation/Scale 3D.");
if (!keying) {
return;
}
@@ -3545,7 +3561,6 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
return;
}
- ERR_FAIL_COND(!root);
// Let's build a node path.
String path = root->get_path_to(p_node);
if (p_sub != "") {
@@ -3554,24 +3569,16 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
NodePath np = path;
- int position_idx = -1;
- int rotation_idx = -1;
- int scale_idx = -1;
+ int track_idx = -1;
for (int i = 0; i < animation->get_track_count(); i++) {
if (animation->track_get_path(i) != np) {
continue;
}
-
- if (animation->track_get_type(i) == Animation::TYPE_POSITION_3D) {
- position_idx = i;
- }
- if (animation->track_get_type(i) == Animation::TYPE_ROTATION_3D) {
- rotation_idx = i;
- }
- if (animation->track_get_type(i) == Animation::TYPE_SCALE_3D) {
- scale_idx = i;
+ if (animation->track_get_type(i) != p_type) {
+ continue;
}
+ track_idx = i;
}
InsertData id;
@@ -3579,48 +3586,30 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
id.query = vformat(TTR("node '%s'"), p_node->get_name());
id.advance = false;
-
- {
- id.track_idx = position_idx;
- id.value = p_xform.origin;
- id.type = Animation::TYPE_POSITION_3D;
- _query_insert(id);
- }
- {
- id.track_idx = rotation_idx;
- id.value = p_xform.basis.get_rotation_quaternion();
- id.type = Animation::TYPE_ROTATION_3D;
- _query_insert(id);
- }
- {
- id.track_idx = scale_idx;
- id.value = p_xform.basis.get_scale();
- id.type = Animation::TYPE_SCALE_3D;
- _query_insert(id);
- }
+ id.track_idx = track_idx;
+ id.value = p_value;
+ id.type = p_type;
+ _query_insert(id);
}
-bool AnimationTrackEditor::has_transform_track(Node3D *p_node, const String &p_sub) {
+bool AnimationTrackEditor::has_track(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type) {
+ ERR_FAIL_COND_V(!root, false);
if (!keying) {
return false;
}
if (!animation.is_valid()) {
return false;
}
- if (!root) {
- return false;
- }
- //let's build a node path
+ // Let's build a node path.
String path = root->get_path_to(p_node);
if (p_sub != "") {
path += ":" + p_sub;
}
- int track_id = animation->find_track(path);
+
+ int track_id = animation->find_track(path, p_type);
if (track_id >= 0) {
- if (animation->track_get_type(track_id) == Animation::TYPE_POSITION_3D || animation->track_get_type(track_id) == Animation::TYPE_ROTATION_3D || animation->track_get_type(track_id) == Animation::TYPE_SCALE_3D) {
- return true;
- }
+ return true;
}
return false;
}
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 2555901557..05cf91de1d 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -527,8 +527,8 @@ public:
void set_anim_pos(float p_pos);
void insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists = false);
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
- void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform);
- bool has_transform_track(Node3D *p_node, const String &p_sub);
+ void insert_transform_key(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type, const Variant p_value);
+ bool has_track(Node3D *p_node, const String &p_sub, const Animation::TrackType p_type);
void make_insert_queue();
void commit_insert_queue();
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index 4ee8b991e4..70ba806c37 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -419,7 +419,7 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se
// Go through other track to find if animation is set
String animation_path = get_animation()->track_get_path(get_track());
animation_path = animation_path.replace(":frame", ":animation");
- int animation_track = get_animation()->find_track(animation_path);
+ int animation_track = get_animation()->find_track(animation_path, get_animation()->track_get_type(get_track()));
float track_time = get_animation()->track_get_key_time(get_track(), p_index);
int animaiton_index = get_animation()->track_find_key(animation_track, track_time);
animation = get_animation()->track_get_key_value(animation_track, animaiton_index);
@@ -511,7 +511,7 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in
// Go through other track to find if animation is set
String animation_path = get_animation()->track_get_path(get_track());
animation_path = animation_path.replace(":frame", ":animation");
- int animation_track = get_animation()->find_track(animation_path);
+ int animation_track = get_animation()->find_track(animation_path, get_animation()->track_get_type(get_track()));
float track_time = get_animation()->track_get_key_time(get_track(), p_index);
int animaiton_index = get_animation()->track_find_key(animation_track, track_time);
animation = get_animation()->track_get_key_value(animation_track, animaiton_index);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index e5d6315ef7..a644e3e991 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -67,7 +67,7 @@
m_name->add_data(FontJapanese); \
m_name->add_data(FontFallback);
-#define MAKE_DEFAULT_FONT(m_name, m_variations, m_base_size) \
+#define MAKE_DEFAULT_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFont.is_valid()) { \
@@ -89,12 +89,11 @@
} \
m_name->set_variation_coordinates(variations); \
} \
- m_name->set_base_size(m_base_size); \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
-#define MAKE_BOLD_FONT(m_name, m_variations, m_base_size) \
+#define MAKE_BOLD_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFontBold.is_valid()) { \
@@ -116,12 +115,11 @@
} \
m_name->set_variation_coordinates(variations); \
} \
- m_name->set_base_size(m_base_size); \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS_BOLD(m_name);
-#define MAKE_SOURCE_FONT(m_name, m_variations, m_base_size) \
+#define MAKE_SOURCE_FONT(m_name, m_variations) \
Ref<Font> m_name; \
m_name.instantiate(); \
if (CustomFontSource.is_valid()) { \
@@ -143,7 +141,6 @@
} \
m_name->set_variation_coordinates(variations); \
} \
- m_name->set_base_size(m_base_size); \
m_name->set_spacing(TextServer::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
@@ -275,7 +272,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<FontData> dfmono = load_cached_internal_font(_font_Hack_Regular, _font_Hack_Regular_size, font_hinting, font_antialiased, true);
// Default font
- MAKE_DEFAULT_FONT(df, String(), default_font_size);
+ MAKE_DEFAULT_FONT(df, String());
p_theme->set_default_theme_font(df); // Default theme font
p_theme->set_default_theme_font_size(default_font_size);
@@ -283,7 +280,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font("main", "EditorFonts", df);
// Bold font
- MAKE_BOLD_FONT(df_bold, String(), default_font_size);
+ MAKE_BOLD_FONT(df_bold, String());
p_theme->set_font_size("bold_size", "EditorFonts", default_font_size);
p_theme->set_font("bold", "EditorFonts", df_bold);
@@ -310,7 +307,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
// Documentation fonts
String code_font_custom_variations = EditorSettings::get_singleton()->get("interface/editor/code_font_custom_variations");
- MAKE_SOURCE_FONT(df_code, code_font_custom_variations, default_font_size);
+ MAKE_SOURCE_FONT(df_code, code_font_custom_variations);
p_theme->set_font_size("doc_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df);
p_theme->set_font_size("doc_bold_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 2d4a3ac788..6a36304ba4 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -884,10 +884,11 @@ public:
flag_rects.push_back(rect2);
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
+ int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Vector2 offset;
offset.y = rect2.size.y * 0.75;
- draw_string(font, rect2.position + offset, itos(layer_index + 1), HALIGN_CENTER, rect2.size.x, -1, on ? text_color_on : text_color);
+ draw_string(font, rect2.position + offset, itos(layer_index + 1), HALIGN_CENTER, rect2.size.x, font_size, on ? text_color_on : text_color);
ofs.x += bsize + 1;
diff --git a/editor/icons/NewKey.svg b/editor/icons/NewKey.svg
new file mode 100644
index 0000000000..fc8507e6c4
--- /dev/null
+++ b/editor/icons/NewKey.svg
@@ -0,0 +1 @@
+<svg enable-background="new 0 0 16 16" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" fill-opacity=".9961"><path d="m13 9h-2v2h-2v2h2v2h2v-2h2v-2h-2z"/><path d="m10 9.723c-.596-.347-1-.985-1-1.723 0-1.104.896-2 2-2s2 .896 2 2h1v2h.445c.344-.591.555-1.268.555-2 0-2.209-1.791-4-4-4-1.822.002-3.414 1.235-3.869 3h-6.131v2h1v2h3v-2h2.133c.16.62.466 1.169.867 1.627v-.627h2z"/></g></svg>
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index 319e5ee25f..bebf05d481 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -950,6 +950,13 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
}
}
}
+
+ bool use_compression = node_settings["compression/enabled"];
+ int anim_compression_page_size = node_settings["compression/page_size"];
+
+ if (use_compression) {
+ _compress_animations(ap, anim_compression_page_size);
+ }
}
return p_node;
@@ -1149,6 +1156,15 @@ void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_
}
}
+void ResourceImporterScene::_compress_animations(AnimationPlayer *anim, int p_page_size_kb) {
+ List<StringName> anim_names;
+ anim->get_animation_list(&anim_names);
+ for (const StringName &E : anim_names) {
+ Ref<Animation> a = anim->get_animation(E);
+ a->compress(p_page_size_kb * 1024);
+ }
+}
+
void ResourceImporterScene::get_internal_import_options(InternalImportCategory p_category, List<ImportOption> *r_options) const {
switch (p_category) {
case INTERNAL_IMPORT_CATEGORY_NODE: {
@@ -1212,6 +1228,8 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_linear_error"), 0.05));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angular_error"), 0.01));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "optimizer/max_angle"), 22));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compression/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compression/page_size", PROPERTY_HINT_RANGE, "4,512,1,suffix:kb"), 8));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/position", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/rotation", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_tracks/scale", PROPERTY_HINT_ENUM, "IfPresent,IfPresentForAll,Never"), 1));
@@ -1320,13 +1338,16 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
}
} break;
case INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE: {
- if (p_option.begins_with("animation/optimizer/") && p_option != "animation/optimizer/enabled" && !bool(p_options["animation/optimizer/enabled"])) {
+ if (p_option.begins_with("optimizer/") && p_option != "optimizer/enabled" && !bool(p_options["optimizer/enabled"])) {
+ return false;
+ }
+ if (p_option.begins_with("compression/") && p_option != "compression/enabled" && !bool(p_options["compression/enabled"])) {
return false;
}
- if (p_option.begins_with("animation/slice_")) {
- int max_slice = p_options["animation/slices/amount"];
- int slice = p_option.get_slice("/", 1).get_slice("_", 1).to_int() - 1;
+ if (p_option.begins_with("slice_")) {
+ int max_slice = p_options["slices/amount"];
+ int slice = p_option.get_slice("_", 1).to_int() - 1;
if (slice >= max_slice) {
return false;
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index e1e7046be5..a192921966 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -261,6 +261,7 @@ public:
Ref<Animation> _save_animation_to_file(Ref<Animation> anim, bool p_save_to_file, String p_save_to_path, bool p_keep_custom_tracks);
void _create_clips(AnimationPlayer *anim, const Array &p_clips, bool p_bake_all);
void _optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle);
+ void _compress_animations(AnimationPlayer *anim, int p_page_size_kb);
Node *pre_import(const String &p_source_file);
virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 59d0b92ba0..5622d0b145 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -391,7 +391,9 @@ void InspectorDock::_transform_keyed(Object *sp, const String &p_sub, const Tran
if (!s) {
return;
}
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, p_key);
+ AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_POSITION_3D, p_key.origin);
+ AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_ROTATION_3D, p_key.basis.get_rotation_quaternion());
+ AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_transform_key(s, p_sub, Animation::TYPE_SCALE_3D, p_key.basis.get_scale());
}
void InspectorDock::_warning_pressed() {
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 8935f715e6..5544d9261e 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -3565,7 +3565,7 @@ void CanvasItemEditor::_draw_hover() {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
- Size2 node_name_size = font->get_string_size(node_name);
+ Size2 node_name_size = font->get_string_size(node_name, font_size);
Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3));
Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4);
@@ -4777,10 +4777,6 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (key_pos) {
ctrl->set_position(Point2());
}
- /*
- if (key_scale)
- AnimationPlayerEditor::get_singleton()->get_track_editor()->insert_node_value_key(ctrl,"rect/size",ctrl->get_size());
- */
}
}
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 0096152cfe..e8086e2fea 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -252,6 +252,14 @@ void ViewportRotationControl::set_viewport(Node3DEditorViewport *p_viewport) {
viewport = p_viewport;
}
+void Node3DEditorViewport::_view_settings_confirmed(real_t p_interp_delta) {
+ // Set FOV override multiplier back to the default, so that the FOV
+ // setting specified in the View menu is correctly applied.
+ cursor.fov_scale = 1.0;
+
+ _update_camera(p_interp_delta);
+}
+
void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
@@ -318,6 +326,8 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) {
equal = false;
} else if (!Math::is_equal_approx(old_camera_cursor.distance, camera_cursor.distance, tolerance)) {
equal = false;
+ } else if (!Math::is_equal_approx(old_camera_cursor.fov_scale, camera_cursor.fov_scale, tolerance)) {
+ equal = false;
}
if (!equal || p_interp_delta == 0 || is_orthogonal != orthogonal) {
@@ -383,7 +393,7 @@ float Node3DEditorViewport::get_zfar() const {
}
float Node3DEditorViewport::get_fov() const {
- return CLAMP(spatial_editor->get_fov(), MIN_FOV, MAX_FOV);
+ return CLAMP(spatial_editor->get_fov() * cursor.fov_scale, MIN_FOV, MAX_FOV);
}
Transform3D Node3DEditorViewport::_get_camera_transform() const {
@@ -1327,17 +1337,25 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
const real_t zoom_factor = 1 + (ZOOM_FREELOOK_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
case MOUSE_BUTTON_WHEEL_UP: {
- if (is_freelook_active()) {
- scale_freelook_speed(zoom_factor);
+ if (b->is_alt_pressed()) {
+ scale_fov(-0.05);
} else {
- scale_cursor_distance(1.0 / zoom_factor);
+ if (is_freelook_active()) {
+ scale_freelook_speed(zoom_factor);
+ } else {
+ scale_cursor_distance(1.0 / zoom_factor);
+ }
}
} break;
case MOUSE_BUTTON_WHEEL_DOWN: {
- if (is_freelook_active()) {
- scale_freelook_speed(1.0 / zoom_factor);
+ if (b->is_alt_pressed()) {
+ scale_fov(0.05);
} else {
- scale_cursor_distance(zoom_factor);
+ if (is_freelook_active()) {
+ scale_freelook_speed(1.0 / zoom_factor);
+ } else {
+ scale_cursor_distance(zoom_factor);
+ }
}
} break;
case MOUSE_BUTTON_RIGHT: {
@@ -2305,6 +2323,18 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
emit_signal(SNAME("toggle_maximize_view"), this);
}
}
+
+ if (ED_IS_SHORTCUT("spatial_editor/decrease_fov", p_event)) {
+ scale_fov(-0.05);
+ }
+
+ if (ED_IS_SHORTCUT("spatial_editor/increase_fov", p_event)) {
+ scale_fov(0.05);
+ }
+
+ if (ED_IS_SHORTCUT("spatial_editor/reset_fov", p_event)) {
+ reset_fov();
+ }
}
// freelook uses most of the useful shortcuts, like save, so its ok
@@ -2472,6 +2502,16 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) {
freelook_active = active_now;
}
+void Node3DEditorViewport::scale_fov(real_t p_fov_offset) {
+ cursor.fov_scale = CLAMP(cursor.fov_scale + p_fov_offset, 0.1, 2.5);
+ surface->update();
+}
+
+void Node3DEditorViewport::reset_fov() {
+ cursor.fov_scale = 1.0;
+ surface->update();
+}
+
void Node3DEditorViewport::scale_cursor_distance(real_t scale) {
real_t min_distance = MAX(camera->get_near() * 4, ZOOM_FREELOOK_MIN);
real_t max_distance = MIN(camera->get_far() / 4, ZOOM_FREELOOK_MAX);
@@ -7343,6 +7383,9 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
ED_SHORTCUT("spatial_editor/align_transform_with_view", TTR("Align Transform with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_M);
ED_SHORTCUT("spatial_editor/align_rotation_with_view", TTR("Align Rotation with View"), KEY_MASK_ALT + KEY_MASK_CMD + KEY_F);
ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F);
+ ED_SHORTCUT("spatial_editor/decrease_fov", TTR("Decrease Field of View"), KEY_MASK_CMD + KEY_EQUAL); // Usually direct access key for `KEY_PLUS`.
+ ED_SHORTCUT("spatial_editor/increase_fov", TTR("Increase Field of View"), KEY_MASK_CMD + KEY_MINUS);
+ ED_SHORTCUT("spatial_editor/reset_fov", TTR("Reset Field of View to Default"), KEY_MASK_CMD + KEY_0);
PopupMenu *p;
@@ -7490,7 +7533,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
settings_vbc->add_margin_child(TTR("View Z-Far:"), settings_zfar);
for (uint32_t i = 0; i < VIEWPORTS_COUNT; ++i) {
- settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_update_camera), varray(0.0));
+ settings_dialog->connect("confirmed", callable_mp(viewports[i], &Node3DEditorViewport::_view_settings_confirmed), varray(0.0));
}
/* XFORM DIALOG */
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5290a8804b..e1318f52a8 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -315,7 +315,7 @@ private:
struct Cursor {
Vector3 pos;
- real_t x_rot, y_rot, distance;
+ real_t x_rot, y_rot, distance, fov_scale;
Vector3 eye_pos; // Used in freelook mode
bool region_select;
Point2 region_begin, region_end;
@@ -325,6 +325,7 @@ private:
x_rot = 0.5;
y_rot = -0.5;
distance = 4;
+ fov_scale = 1.0;
region_select = false;
}
};
@@ -333,6 +334,8 @@ private:
Cursor cursor; // Immediate cursor
Cursor camera_cursor; // That one may be interpolated (don't modify this one except for smoothing purposes)
+ void scale_fov(real_t p_fov_offset);
+ void reset_fov();
void scale_cursor_distance(real_t scale);
void set_freelook_active(bool active_now);
@@ -349,6 +352,7 @@ private:
void set_message(String p_message, float p_time = 5);
+ void _view_settings_confirmed(real_t p_interp_delta);
void _update_camera(real_t p_interp_delta);
Transform3D to_camera_transform(const Cursor &p_cursor) const;
void _draw();
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 708eaf2c46..0b8a56503c 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -54,6 +54,7 @@ void BoneTransformEditor::create_editors() {
enabled_checkbox = memnew(EditorPropertyCheck());
enabled_checkbox->set_label("Pose Enabled");
+ enabled_checkbox->set_selectable(false);
enabled_checkbox->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
section->get_vbox()->add_child(enabled_checkbox);
@@ -61,21 +62,27 @@ void BoneTransformEditor::create_editors() {
position_property = memnew(EditorPropertyVector3());
position_property->setup(-10000, 10000, 0.001f, true);
position_property->set_label("Position");
+ position_property->set_selectable(false);
position_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
+ position_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
section->get_vbox()->add_child(position_property);
// Rotation property.
rotation_property = memnew(EditorPropertyQuaternion());
rotation_property->setup(-10000, 10000, 0.001f, true);
rotation_property->set_label("Rotation");
+ rotation_property->set_selectable(false);
rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
+ rotation_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
section->get_vbox()->add_child(rotation_property);
// Scale property.
scale_property = memnew(EditorPropertyVector3());
scale_property->setup(-10000, 10000, 0.001f, true);
scale_property->set_label("Scale");
+ scale_property->set_selectable(false);
scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed));
+ scale_property->connect("property_keyed", callable_mp(this, &BoneTransformEditor::_property_keyed));
section->get_vbox()->add_child(scale_property);
// Transform/Matrix section.
@@ -87,6 +94,7 @@ void BoneTransformEditor::create_editors() {
rest_matrix = memnew(EditorPropertyTransform3D());
rest_matrix->setup(-10000, 10000, 0.001f, true);
rest_matrix->set_label("Transform");
+ rest_matrix->set_selectable(false);
rest_section->get_vbox()->add_child(rest_matrix);
}
@@ -116,6 +124,12 @@ BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) :
undo_redo = EditorNode::get_undo_redo();
}
+void BoneTransformEditor::set_keyable(const bool p_keyable) {
+ position_property->set_keying(p_keyable);
+ rotation_property->set_keying(p_keyable);
+ scale_property->set_keying(p_keyable);
+}
+
void BoneTransformEditor::set_target(const String &p_prop) {
enabled_checkbox->set_object_and_property(skeleton, p_prop + "enabled");
enabled_checkbox->update_property();
@@ -133,6 +147,23 @@ void BoneTransformEditor::set_target(const String &p_prop) {
rest_matrix->update_property();
}
+void BoneTransformEditor::_property_keyed(const String &p_path, bool p_advance) {
+ AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
+ PackedStringArray split = p_path.split("/");
+ if (split.size() == 3 && split[0] == "bones") {
+ int bone_idx = split[1].to_int();
+ if (split[2] == "position") {
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_POSITION_3D, skeleton->get(p_path));
+ }
+ if (split[2] == "rotation") {
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_ROTATION_3D, skeleton->get(p_path));
+ }
+ if (split[2] == "scale") {
+ te->insert_transform_key(skeleton, skeleton->get_bone_name(bone_idx), Animation::TYPE_SCALE_3D, skeleton->get(p_path));
+ }
+ }
+}
+
void BoneTransformEditor::_update_properties() {
if (!skeleton) {
return;
@@ -141,30 +172,30 @@ void BoneTransformEditor::_update_properties() {
List<PropertyInfo> props;
skeleton->get_property_list(&props);
for (const PropertyInfo &E : props) {
- PackedStringArray spr = E.name.split("/");
- if (spr.size() == 3 && spr[0] == "bones") {
- if (spr[1].to_int() == selected) {
- if (spr[2] == "enabled") {
+ PackedStringArray split = E.name.split("/");
+ if (split.size() == 3 && split[0] == "bones") {
+ if (split[1].to_int() == selected) {
+ if (split[2] == "enabled") {
enabled_checkbox->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
enabled_checkbox->update_property();
enabled_checkbox->update();
}
- if (spr[2] == "position") {
+ if (split[2] == "position") {
position_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
position_property->update_property();
position_property->update();
}
- if (spr[2] == "rotation") {
+ if (split[2] == "rotation") {
rotation_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
rotation_property->update_property();
rotation_property->update();
}
- if (spr[2] == "scale") {
+ if (split[2] == "scale") {
scale_property->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
scale_property->update_property();
scale_property->update();
}
- if (spr[2] == "rest") {
+ if (split[2] == "rest") {
rest_matrix->set_read_only(E.usage & PROPERTY_USAGE_READ_ONLY);
rest_matrix->update_property();
rest_matrix->update();
@@ -178,12 +209,16 @@ Skeleton3DEditor *Skeleton3DEditor::singleton = nullptr;
void Skeleton3DEditor::set_keyable(const bool p_keyable) {
keyable = p_keyable;
- skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INSERT_KEYS, !p_keyable);
- skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INSERT_KEYS_EXISTED, !p_keyable);
+ if (p_keyable) {
+ animation_hb->show();
+ } else {
+ animation_hb->hide();
+ }
};
-void Skeleton3DEditor::set_rest_options_enabled(const bool p_rest_options_enabled) {
- rest_options->get_popup()->set_item_disabled(REST_OPTION_POSE_TO_REST, !p_rest_options_enabled);
+void Skeleton3DEditor::set_bone_options_enabled(const bool p_bone_options_enabled) {
+ skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_INIT_SELECTED_POSES, !p_bone_options_enabled);
+ skeleton_options->get_popup()->set_item_disabled(SKELETON_OPTION_SELECTED_POSES_TO_RESTS, !p_bone_options_enabled);
};
void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
@@ -192,62 +227,76 @@ void Skeleton3DEditor::_on_click_skeleton_option(int p_skeleton_option) {
}
switch (p_skeleton_option) {
- case SKELETON_OPTION_CREATE_PHYSICAL_SKELETON: {
- create_physical_skeleton();
+ case SKELETON_OPTION_INIT_ALL_POSES: {
+ init_pose(true);
break;
}
- case SKELETON_OPTION_INIT_POSE: {
- init_pose();
+ case SKELETON_OPTION_INIT_SELECTED_POSES: {
+ init_pose(false);
break;
}
- case SKELETON_OPTION_INSERT_KEYS: {
- insert_keys(true);
+ case SKELETON_OPTION_ALL_POSES_TO_RESTS: {
+ pose_to_rest(true);
break;
}
- case SKELETON_OPTION_INSERT_KEYS_EXISTED: {
- insert_keys(false);
+ case SKELETON_OPTION_SELECTED_POSES_TO_RESTS: {
+ pose_to_rest(false);
+ break;
+ }
+ case SKELETON_OPTION_CREATE_PHYSICAL_SKELETON: {
+ create_physical_skeleton();
break;
}
}
}
-void Skeleton3DEditor::_on_click_rest_option(int p_rest_option) {
+void Skeleton3DEditor::init_pose(const bool p_all_bones) {
if (!skeleton) {
return;
}
-
- switch (p_rest_option) {
- case REST_OPTION_POSE_TO_REST: {
- pose_to_rest();
- break;
- }
- }
-}
-
-void Skeleton3DEditor::init_pose() {
const int bone_len = skeleton->get_bone_count();
if (!bone_len) {
return;
}
+
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS);
- for (int i = 0; i < bone_len; i++) {
- Transform3D rest = skeleton->get_bone_rest(i);
- ur->add_do_method(skeleton, "set_bone_pose_position", i, rest.origin);
- ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quaternion());
- ur->add_do_method(skeleton, "set_bone_pose_scale", i, rest.basis.get_scale());
- ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i));
- ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i));
- ur->add_undo_method(skeleton, "set_bone_pose_scale", i, skeleton->get_bone_pose_scale(i));
+ if (p_all_bones) {
+ for (int i = 0; i < bone_len; i++) {
+ Transform3D rest = skeleton->get_bone_rest(i);
+ ur->add_do_method(skeleton, "set_bone_pose_position", i, rest.origin);
+ ur->add_do_method(skeleton, "set_bone_pose_rotation", i, rest.basis.get_rotation_quaternion());
+ ur->add_do_method(skeleton, "set_bone_pose_scale", i, rest.basis.get_scale());
+ ur->add_undo_method(skeleton, "set_bone_pose_position", i, skeleton->get_bone_pose_position(i));
+ ur->add_undo_method(skeleton, "set_bone_pose_rotation", i, skeleton->get_bone_pose_rotation(i));
+ ur->add_undo_method(skeleton, "set_bone_pose_scale", i, skeleton->get_bone_pose_scale(i));
+ }
+ } else {
+ // Todo: Do method with multiple bone selection.
+ if (selected_bone == -1) {
+ ur->commit_action();
+ return;
+ }
+ Transform3D rest = skeleton->get_bone_rest(selected_bone);
+ ur->add_do_method(skeleton, "set_bone_pose_position", selected_bone, rest.origin);
+ ur->add_do_method(skeleton, "set_bone_pose_rotation", selected_bone, rest.basis.get_rotation_quaternion());
+ ur->add_do_method(skeleton, "set_bone_pose_scale", selected_bone, rest.basis.get_scale());
+ ur->add_undo_method(skeleton, "set_bone_pose_position", selected_bone, skeleton->get_bone_pose_position(selected_bone));
+ ur->add_undo_method(skeleton, "set_bone_pose_rotation", selected_bone, skeleton->get_bone_pose_rotation(selected_bone));
+ ur->add_undo_method(skeleton, "set_bone_pose_scale", selected_bone, skeleton->get_bone_pose_scale(selected_bone));
}
ur->commit_action();
}
-void Skeleton3DEditor::insert_keys(bool p_all_bones) {
+void Skeleton3DEditor::insert_keys(const bool p_all_bones) {
if (!skeleton) {
return;
}
+ bool pos_enabled = key_loc_button->is_pressed();
+ bool rot_enabled = key_rot_button->is_pressed();
+ bool scl_enabled = key_scale_button->is_pressed();
+
int bone_len = skeleton->get_bone_count();
Node *root = EditorNode::get_singleton()->get_tree()->get_root();
String path = root->get_path_to(skeleton);
@@ -261,26 +310,44 @@ void Skeleton3DEditor::insert_keys(bool p_all_bones) {
continue;
}
- if (!p_all_bones && !te->has_transform_track(skeleton, name)) {
- continue;
+ if (pos_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_POSITION_3D))) {
+ te->insert_transform_key(skeleton, name, Animation::TYPE_POSITION_3D, skeleton->get_bone_pose_position(i));
+ }
+ if (rot_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_ROTATION_3D))) {
+ te->insert_transform_key(skeleton, name, Animation::TYPE_ROTATION_3D, skeleton->get_bone_pose_rotation(i));
+ }
+ if (scl_enabled && (p_all_bones || te->has_track(skeleton, name, Animation::TYPE_SCALE_3D))) {
+ te->insert_transform_key(skeleton, name, Animation::TYPE_SCALE_3D, skeleton->get_bone_pose_scale(i));
}
-
- Transform3D tform = skeleton->get_bone_pose(i);
- te->insert_transform_key(skeleton, name, tform);
}
te->commit_insert_queue();
}
-void Skeleton3DEditor::pose_to_rest() {
+void Skeleton3DEditor::pose_to_rest(const bool p_all_bones) {
if (!skeleton) {
return;
}
+ const int bone_len = skeleton->get_bone_count();
+ if (!bone_len) {
+ return;
+ }
- // Todo: Do method with multiple bone selection.
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Set Bone Rest"), UndoRedo::MERGE_ENDS);
- ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_pose(selected_bone));
- ur->add_undo_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone));
+ if (p_all_bones) {
+ for (int i = 0; i < bone_len; i++) {
+ ur->add_do_method(skeleton, "set_bone_rest", i, skeleton->get_bone_pose(i));
+ ur->add_undo_method(skeleton, "set_bone_rest", i, skeleton->get_bone_rest(i));
+ }
+ } else {
+ // Todo: Do method with multiple bone selection.
+ if (selected_bone == -1) {
+ ur->commit_action();
+ return;
+ }
+ ur->add_do_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_pose(selected_bone));
+ ur->add_undo_method(skeleton, "set_bone_rest", selected_bone, skeleton->get_bone_rest(selected_bone));
+ }
ur->commit_action();
}
@@ -466,11 +533,12 @@ void Skeleton3DEditor::_joint_tree_selection_changed() {
const String bone_path = "bones/" + itos(b_idx) + "/";
pose_editor->set_target(bone_path);
+ pose_editor->set_keyable(keyable);
selected_bone = b_idx;
}
}
pose_editor->set_visible(selected);
- set_rest_options_enabled(selected);
+ set_bone_options_enabled(selected);
_update_properties();
_update_gizmo_visible();
}
@@ -549,43 +617,82 @@ void Skeleton3DEditor::create_editors() {
skeleton_options->set_text(TTR("Skeleton3D"));
skeleton_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Skeleton3D"), SNAME("EditorIcons")));
- skeleton_options->get_popup()->add_item(TTR("Init pose"), SKELETON_OPTION_INIT_POSE);
- skeleton_options->get_popup()->add_item(TTR("Insert key of all bone poses"), SKELETON_OPTION_INSERT_KEYS);
- skeleton_options->get_popup()->add_item(TTR("Insert key of bone poses already exist track"), SKELETON_OPTION_INSERT_KEYS_EXISTED);
- skeleton_options->get_popup()->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
-
- skeleton_options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
+ // Skeleton options.
+ PopupMenu *p = skeleton_options->get_popup();
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_all_poses", TTR("Init all Poses")), SKELETON_OPTION_INIT_ALL_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/init_selected_poses", TTR("Init selected Poses")), SKELETON_OPTION_INIT_SELECTED_POSES);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/all_poses_to_rests", TTR("Apply all poses to rests")), SKELETON_OPTION_ALL_POSES_TO_RESTS);
+ p->add_shortcut(ED_SHORTCUT("skeleton_3d_editor/selected_poses_to_rests", TTR("Apply selected poses to rests")), SKELETON_OPTION_SELECTED_POSES_TO_RESTS);
+ p->add_item(TTR("Create physical skeleton"), SKELETON_OPTION_CREATE_PHYSICAL_SKELETON);
- // Create Rest Option in Top Menu Bar.
- rest_options = memnew(MenuButton);
- ne->add_control_to_menu_panel(rest_options);
-
- rest_options->set_text(TTR("Edit Rest"));
- rest_options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")));
-
- rest_options->get_popup()->add_item(TTR("Apply current pose to rest"), REST_OPTION_POSE_TO_REST);
- rest_options->get_popup()->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_rest_option));
- set_rest_options_enabled(false);
+ p->connect("id_pressed", callable_mp(this, &Skeleton3DEditor::_on_click_skeleton_option));
+ set_bone_options_enabled(false);
Vector<Variant> button_binds;
button_binds.resize(1);
edit_mode_button = memnew(Button);
ne->add_control_to_menu_panel(edit_mode_button);
- edit_mode_button->set_tooltip(TTR("Edit Mode\nShow buttons on joints."));
- edit_mode_button->set_toggle_mode(true);
edit_mode_button->set_flat(true);
+ edit_mode_button->set_toggle_mode(true);
+ edit_mode_button->set_focus_mode(FOCUS_NONE);
+ edit_mode_button->set_tooltip(TTR("Edit Mode\nShow buttons on joints."));
edit_mode_button->connect("toggled", callable_mp(this, &Skeleton3DEditor::edit_mode_toggled));
edit_mode = false;
- set_keyable(te->has_keying());
-
if (skeleton) {
skeleton->add_child(handles_mesh_instance);
handles_mesh_instance->set_skeleton_path(NodePath(""));
}
+ // Keying buttons.
+ animation_hb = memnew(HBoxContainer);
+ ne->add_control_to_menu_panel(animation_hb);
+ animation_hb->add_child(memnew(VSeparator));
+ animation_hb->hide();
+
+ key_loc_button = memnew(Button);
+ key_loc_button->set_flat(true);
+ key_loc_button->set_toggle_mode(true);
+ key_loc_button->set_pressed(false);
+ key_loc_button->set_focus_mode(FOCUS_NONE);
+ key_loc_button->set_tooltip(TTR("Translation mask for inserting keys."));
+ animation_hb->add_child(key_loc_button);
+
+ key_rot_button = memnew(Button);
+ key_rot_button->set_flat(true);
+ key_rot_button->set_toggle_mode(true);
+ key_rot_button->set_pressed(true);
+ key_rot_button->set_focus_mode(FOCUS_NONE);
+ key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys."));
+ animation_hb->add_child(key_rot_button);
+
+ key_scale_button = memnew(Button);
+ key_scale_button->set_flat(true);
+ key_scale_button->set_toggle_mode(true);
+ key_scale_button->set_pressed(false);
+ key_scale_button->set_focus_mode(FOCUS_NONE);
+ key_scale_button->set_tooltip(TTR("Scale mask for inserting keys."));
+ animation_hb->add_child(key_scale_button);
+
+ key_insert_button = memnew(Button);
+ key_insert_button->set_flat(true);
+ key_insert_button->set_focus_mode(FOCUS_NONE);
+ key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(false));
+ key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track."));
+ key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), KEY_INSERT));
+ animation_hb->add_child(key_insert_button);
+
+ key_insert_all_button = memnew(Button);
+ key_insert_all_button->set_flat(true);
+ key_insert_all_button->set_focus_mode(FOCUS_NONE);
+ key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys), varray(true));
+ key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses."));
+ key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KEY_MASK_CMD + KEY_INSERT));
+ animation_hb->add_child(key_insert_all_button);
+
+ // Bone tree.
const Color section_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
EditorInspectorSection *bones_section = memnew(EditorInspectorSection);
@@ -613,12 +720,19 @@ void Skeleton3DEditor::create_editors() {
pose_editor->set_label(TTR("Bone Transform"));
pose_editor->set_visible(false);
add_child(pose_editor);
+
+ set_keyable(te->has_keying());
}
void Skeleton3DEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
- edit_mode_button->set_icon(get_theme_icon("ToolBoneSelect", "EditorIcons"));
+ edit_mode_button->set_icon(get_theme_icon(SNAME("ToolBoneSelect"), SNAME("EditorIcons")));
+ key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons")));
+ key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons")));
+ key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons")));
+ key_insert_button->set_icon(get_theme_icon(SNAME("Key"), SNAME("EditorIcons")));
+ key_insert_all_button->set_icon(get_theme_icon(SNAME("NewKey"), SNAME("EditorIcons")));
get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT);
break;
}
@@ -643,7 +757,6 @@ void Skeleton3DEditor::_node_removed(Node *p_node) {
if (skeleton && p_node == skeleton) {
skeleton = nullptr;
skeleton_options->hide();
- rest_options->hide();
}
_update_properties();
@@ -655,7 +768,6 @@ void Skeleton3DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_joint_tree_rmb_select"), &Skeleton3DEditor::_joint_tree_rmb_select);
ClassDB::bind_method(D_METHOD("_update_properties"), &Skeleton3DEditor::_update_properties);
ClassDB::bind_method(D_METHOD("_on_click_skeleton_option"), &Skeleton3DEditor::_on_click_skeleton_option);
- ClassDB::bind_method(D_METHOD("_on_click_rest_option"), &Skeleton3DEditor::_on_click_rest_option);
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &Skeleton3DEditor::get_drag_data_fw);
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &Skeleton3DEditor::can_drop_data_fw);
@@ -866,6 +978,11 @@ Skeleton3DEditor::~Skeleton3DEditor() {
Node3DEditor *ne = Node3DEditor::get_singleton();
+ if (animation_hb) {
+ ne->remove_control_from_menu_panel(animation_hb);
+ memdelete(animation_hb);
+ }
+
if (separator) {
ne->remove_control_from_menu_panel(separator);
memdelete(separator);
@@ -876,11 +993,6 @@ Skeleton3DEditor::~Skeleton3DEditor() {
memdelete(skeleton_options);
}
- if (rest_options) {
- ne->remove_control_from_menu_panel(rest_options);
- memdelete(rest_options);
- }
-
if (edit_mode_button) {
ne->remove_control_from_menu_panel(edit_mode_button);
memdelete(edit_mode_button);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 3b4dd362fb..1dd2d2281d 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -45,7 +45,6 @@ class Joint;
class PhysicalBone3D;
class Skeleton3DEditorPlugin;
class Button;
-class CheckBox;
class BoneTransformEditor : public VBoxContainer {
GDCLASS(BoneTransformEditor, VBoxContainer);
@@ -67,9 +66,6 @@ class BoneTransformEditor : public VBoxContainer {
UndoRedo *undo_redo;
- // Button *key_button = nullptr;
-
- bool keyable = false;
bool toggle_enabled = false;
bool updating = false;
@@ -79,6 +75,8 @@ class BoneTransformEditor : public VBoxContainer {
void _value_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing);
+ void _property_keyed(const String &p_path, bool p_advance);
+
protected:
void _notification(int p_what);
@@ -88,6 +86,7 @@ public:
// Which transform target to modify.
void set_target(const String &p_prop);
void set_label(const String &p_label) { label = p_label; }
+ void set_keyable(const bool p_keyable);
void _update_properties();
};
@@ -98,14 +97,11 @@ class Skeleton3DEditor : public VBoxContainer {
friend class Skeleton3DEditorPlugin;
enum SkeletonOption {
- SKELETON_OPTION_INIT_POSE,
- SKELETON_OPTION_INSERT_KEYS,
- SKELETON_OPTION_INSERT_KEYS_EXISTED,
- SKELETON_OPTION_CREATE_PHYSICAL_SKELETON
- };
-
- enum RestOption {
- REST_OPTION_POSE_TO_REST
+ SKELETON_OPTION_INIT_ALL_POSES,
+ SKELETON_OPTION_INIT_SELECTED_POSES,
+ SKELETON_OPTION_ALL_POSES_TO_RESTS,
+ SKELETON_OPTION_SELECTED_POSES_TO_RESTS,
+ SKELETON_OPTION_CREATE_PHYSICAL_SKELETON,
};
struct BoneInfo {
@@ -124,11 +120,17 @@ class Skeleton3DEditor : public VBoxContainer {
VSeparator *separator;
MenuButton *skeleton_options = nullptr;
- MenuButton *rest_options = nullptr;
Button *edit_mode_button;
bool edit_mode = false;
+ HBoxContainer *animation_hb;
+ Button *key_loc_button;
+ Button *key_rot_button;
+ Button *key_scale_button;
+ Button *key_insert_button;
+ Button *key_insert_all_button;
+
EditorFileDialog *file_dialog = nullptr;
bool keyable;
@@ -136,7 +138,6 @@ class Skeleton3DEditor : public VBoxContainer {
static Skeleton3DEditor *singleton;
void _on_click_skeleton_option(int p_skeleton_option);
- void _on_click_rest_option(int p_rest_option);
void _file_selected(const String &p_file);
TreeItem *_find(TreeItem *p_node, const NodePath &p_path);
void edit_mode_toggled(const bool pressed);
@@ -148,9 +149,10 @@ class Skeleton3DEditor : public VBoxContainer {
void create_editors();
- void init_pose();
- void insert_keys(bool p_all_bones);
- void pose_to_rest();
+ void init_pose(const bool p_all_bones);
+ void pose_to_rest(const bool p_all_bones);
+
+ void insert_keys(const bool p_all_bones);
void create_physical_skeleton();
PhysicalBone3D *create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos);
@@ -160,7 +162,7 @@ class Skeleton3DEditor : public VBoxContainer {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
void set_keyable(const bool p_keyable);
- void set_rest_options_enabled(const bool p_rest_options_enabled);
+ void set_bone_options_enabled(const bool p_bone_options_enabled);
// Handle.
MeshInstance3D *handles_mesh_instance;
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index d26d0ec39d..e13a10fe3f 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -117,7 +117,7 @@ void ThemeEditorPreview::_draw_picker_overlay() {
}
Rect2 highlight_label_rect = highlight_rect;
- highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name);
+ highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, theme_cache.font_size);
int margin_top = theme_cache.preview_picker_label->get_margin(SIDE_TOP);
int margin_left = theme_cache.preview_picker_label->get_margin(SIDE_LEFT);
@@ -133,7 +133,7 @@ void ThemeEditorPreview::_draw_picker_overlay() {
Point2 label_pos = highlight_label_rect.position;
label_pos.y += highlight_label_rect.size.y - margin_bottom;
label_pos.x += margin_left;
- picker_overlay->draw_string(theme_cache.preview_picker_font, label_pos, highlight_name);
+ picker_overlay->draw_string(theme_cache.preview_picker_font, label_pos, highlight_name, HALIGN_LEFT, -1, theme_cache.font_size);
}
}
@@ -188,6 +188,7 @@ void ThemeEditorPreview::_notification(int p_what) {
theme_cache.preview_picker_overlay_color = get_theme_color(SNAME("preview_picker_overlay_color"), SNAME("ThemeEditor"));
theme_cache.preview_picker_label = get_theme_stylebox(SNAME("preview_picker_label"), SNAME("ThemeEditor"));
theme_cache.preview_picker_font = get_theme_font(SNAME("status_source"), SNAME("EditorFonts"));
+ theme_cache.font_size = get_theme_font_size(SNAME("font_size"), SNAME("EditorFonts"));
} break;
case NOTIFICATION_PROCESS: {
time_left -= get_process_delta_time();
diff --git a/editor/plugins/theme_editor_preview.h b/editor/plugins/theme_editor_preview.h
index 4e1b149e70..f973119257 100644
--- a/editor/plugins/theme_editor_preview.h
+++ b/editor/plugins/theme_editor_preview.h
@@ -65,6 +65,7 @@ class ThemeEditorPreview : public VBoxContainer {
Color preview_picker_overlay_color;
Ref<StyleBox> preview_picker_label;
Ref<Font> preview_picker_font;
+ int font_size = 16;
} theme_cache;
double time_left = 0;
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 104f46f773..e9d80bb4b8 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -987,6 +987,7 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
p_canvas_item->draw_rect(rect, value);
} else {
Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = TileSetEditor::get_singleton()->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
String text;
switch (value.get_type()) {
case Variant::INT:
@@ -1018,8 +1019,8 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2
}
}
- Vector2 string_size = font->get_string_size(text);
- p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, font_size);
+ p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
}
}
@@ -1582,6 +1583,7 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
// Dim terrains with wrong terrain set.
Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = TileSetEditor::get_singleton()->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
for (int i = 0; i < p_tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i coords = p_tile_set_atlas_source->get_tile_id(i);
if (coords != hovered_coords) {
@@ -1604,8 +1606,8 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas
} else {
text = "-";
}
- Vector2 string_size = font->get_string_size(text);
- p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, font_size);
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
}
}
}
@@ -1755,6 +1757,7 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
// Dim terrains with wrong terrain set.
Ref<Font> font = TileSetEditor::get_singleton()->get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ int font_size = TileSetEditor::get_singleton()->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"));
for (int i = 0; i < p_tile_set_atlas_source->get_tiles_count(); i++) {
Vector2i coords = p_tile_set_atlas_source->get_tile_id(i);
for (int j = 1; j < p_tile_set_atlas_source->get_alternative_tiles_count(coords); j++) {
@@ -1779,8 +1782,8 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til
} else {
text = "-";
}
- Vector2 string_size = font->get_string_size(text);
- p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, -1, color, 1, Color(0, 0, 0, 1));
+ Vector2 string_size = font->get_string_size(text, font_size);
+ p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HALIGN_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1));
}
}
}
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index 1ba7d4f786..67b76771d2 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -1008,7 +1008,7 @@ msgstr "لا نتائج من أجل \"%s\"."
#: editor/create_dialog.cpp editor/property_selector.cpp
msgid "No description available for %s."
-msgstr "ليس هناك وص٠مناسب لأجل s%."
+msgstr "ليس هناك وص٠مناسب لأجل %s."
#: editor/create_dialog.cpp editor/editor_file_dialog.cpp
#: editor/filesystem_dock.cpp
@@ -4262,15 +4262,15 @@ msgstr "جاري البحث..."
#: editor/find_in_files.cpp
msgid "%d match in %d file."
-msgstr "d% تطابق ÙÙŠ d% الملÙ."
+msgstr "%d تطابق ÙÙŠ %d الملÙ."
#: editor/find_in_files.cpp
msgid "%d matches in %d file."
-msgstr "d% تطابقات ÙÙŠ d% الملÙ."
+msgstr "%d تطابقات ÙÙŠ %d الملÙ."
#: editor/find_in_files.cpp
msgid "%d matches in %d files."
-msgstr "d% تطابقات ÙÙŠ d% الملÙ."
+msgstr "%d تطابقات ÙÙŠ %d الملÙ."
#: editor/groups_editor.cpp
msgid "Add to Group"
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index e6fd202dde..26f7646086 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -21,7 +21,7 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-10-13 09:34+0000\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
"Last-Translator: Xavier Gomez <hiulit@gmail.com>\n"
"Language-Team: Catalan <https://hosted.weblate.org/projects/godot-engine/"
"godot/ca/>\n"
@@ -747,7 +747,6 @@ msgid "Whole Words"
msgstr "Paraules senceres"
#: editor/code_editor.cpp
-#, fuzzy
msgid "Replace"
msgstr "Reemplaçar"
@@ -2158,7 +2157,6 @@ msgid "Constants"
msgstr "Constants"
#: editor/editor_help.cpp
-#, fuzzy
msgid "Property Descriptions"
msgstr "Descripcions de la Propietat"
@@ -2662,7 +2660,6 @@ msgid "Reload Saved Scene"
msgstr "Desa Escena"
#: editor/editor_node.cpp
-#, fuzzy
msgid ""
"The current scene has unsaved changes.\n"
"Reload the saved scene anyway? This action cannot be undone."
@@ -3194,9 +3191,8 @@ msgid "Suggest a Feature"
msgstr ""
#: editor/editor_node.cpp
-#, fuzzy
msgid "Send Docs Feedback"
-msgstr "Enviar suggeriments sobre la documentació"
+msgstr "Enviar suggeriments sobre la Documentació"
#: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp
msgid "Community"
@@ -3220,9 +3216,8 @@ msgid "Play"
msgstr "Reprodueix"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Pause the scene execution for debugging."
-msgstr "Pausa l’execució d’escena per a la depuració."
+msgstr "Posa en pausa l'execució de l'escena per a depurar-la."
#: editor/editor_node.cpp
msgid "Pause Scene"
@@ -3782,12 +3777,11 @@ msgid "Cannot remove temporary file:"
msgstr "No es pot desar el Tema:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid ""
"Templates installation failed.\n"
"The problematic templates archives can be found at '%s'."
msgstr ""
-"No s'han pogut instal·lar les plantilles. \n"
+"No s'han pogut instal·lar les plantilles.\n"
"Les plantilles problemàtics es troben a '%s'."
#: editor/export_template_manager.cpp
@@ -4906,11 +4900,10 @@ msgstr ""
"els noms de les pistes."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
-#, fuzzy
msgid "Player path set is invalid, so unable to retrieve track names."
msgstr ""
-"El camí del reproductor assignat no és vàlid, de manera que no pot recuperar "
-"els noms de les pistes."
+"El camí del reproductor assignat no és vàlid, de manera que no s'ha pogut "
+"recuperar els noms de les pistes."
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/root_motion_editor_plugin.cpp
@@ -5136,7 +5129,6 @@ msgid "Include Gizmos (3D)"
msgstr "Inclou Gizmos (3D)"
#: editor/plugins/animation_player_editor_plugin.cpp
-#, fuzzy
msgid "Pin AnimationPlayer"
msgstr "Fixar AnimationPlayer"
@@ -5468,14 +5460,12 @@ msgid "Redirect loop."
msgstr "Bucle de redirecció."
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Request failed, timeout"
msgstr "La sol·licitud ha fallat, s'ha esgotat el temps d'espera"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Timeout."
-msgstr "Temps esgotat."
+msgstr "Temps d'espera esgotat."
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Failed:"
@@ -5539,7 +5529,6 @@ msgid "Download for this asset is already in progress!"
msgstr "Ja s'està baixant aquest actiu!"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Recently Updated"
msgstr "Actualitzat Recentment"
@@ -5548,12 +5537,10 @@ msgid "Least Recently Updated"
msgstr "Actualitzacions menys recents"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Name (A-Z)"
msgstr "Nom (A-Z)"
#: editor/plugins/asset_library_editor_plugin.cpp
-#, fuzzy
msgid "Name (Z-A)"
msgstr "Nom (Z-A)"
@@ -5707,9 +5694,8 @@ msgid "Grid Step:"
msgstr "Pas de la Graella:"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Primary Line Every:"
-msgstr "Línia principal cada:"
+msgstr "Línia Principal Cada:"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -6100,7 +6086,6 @@ msgid "Snapping Options"
msgstr "Opcions d'Ajustament"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Use Rotation Snap"
msgstr "Utilitzar Ajustament de Rotació"
@@ -6131,7 +6116,6 @@ msgid "Snap to Parent"
msgstr "Ajustar al Pare"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Snap to Node Anchor"
msgstr "Ajustar a l'Àncora del Node"
@@ -6144,9 +6128,8 @@ msgid "Snap to Node Center"
msgstr "Ajustar al centre del node"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Snap to Other Nodes"
-msgstr "Ajustar als altres nodes"
+msgstr "Ajustar a altres Nodes"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Snap to Guides"
@@ -6181,9 +6164,8 @@ msgid "Show Bones"
msgstr "Mostra els Ossos"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Make Custom Bone(s) from Node(s)"
-msgstr "Fer os(sos) personalitzat(s) a partir de Node(s)"
+msgstr "Crear os(sos) personalitzat(s) a partir de Node(s)"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -6233,9 +6215,8 @@ msgid "Frame Selection"
msgstr "Enquadra la Selecció"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Preview Canvas Scale"
-msgstr "Vista prèvia de l'escala del llenç"
+msgstr "Vista prèvia de l'Escala del Llenç"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
@@ -6578,9 +6559,8 @@ msgid "Mesh is empty!"
msgstr "La malla és buida!"
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#, fuzzy
msgid "Couldn't create a Trimesh collision shape."
-msgstr "Crea una Col·lisió entre malles de triangles germanes."
+msgstr "No s'ha pogut crear una forma de col·lisió Trimesh."
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Static Trimesh Body"
@@ -6772,18 +6752,16 @@ msgid "Remove item %d?"
msgstr "Elimina l'element %d?"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid ""
"Update from existing scene?:\n"
"%s"
msgstr ""
-"Actualitzar des d'una 'Escena existent?:\n"
+"Actualitzar des de l'Escena existent?:\n"
"%s"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Mesh Library"
-msgstr "Biblioteca de Models (MeshLibrary)"
+msgstr "Biblioteca de Malles"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Add Item"
@@ -6906,7 +6884,6 @@ msgstr "Crea un Polígon de Navegació"
#: editor/plugins/particles_2d_editor_plugin.cpp
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "Convert to CPUParticles"
msgstr "Convertir a ParticulesCPU"
@@ -6942,9 +6919,8 @@ msgid "The geometry doesn't contain any faces."
msgstr "El Node no conté cap geometria (cares)."
#: editor/plugins/particles_editor_plugin.cpp
-#, fuzzy
msgid "\"%s\" doesn't inherit from Spatial."
-msgstr "\"% s\" no hereta de Spatial."
+msgstr "\"%s\" no hereta de Spatial."
#: editor/plugins/particles_editor_plugin.cpp
#, fuzzy
@@ -7253,14 +7229,12 @@ msgid "Scale Polygon"
msgstr "Escala el Polígon"
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Create a custom polygon. Enables custom polygon rendering."
msgstr ""
-"Crear polígon personalitzat. Habilita el renderitzat de polígons "
+"Crear un polígon personalitzat. S'habilita el renderitzat de polígons "
"personalitzats."
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid ""
"Remove a custom polygon. If none remain, custom polygon rendering is "
"disabled."
@@ -7273,9 +7247,8 @@ msgid "Paint weights with specified intensity."
msgstr "Pinta pesos amb la intensitat especificada."
#: editor/plugins/polygon_2d_editor_plugin.cpp
-#, fuzzy
msgid "Unpaint weights with specified intensity."
-msgstr "Despinta el pes amb la intensitat especificada."
+msgstr "Despinta pesos amb la intensitat especificada."
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Radius:"
@@ -7424,7 +7397,6 @@ msgid "AnimationTree has no path set to an AnimationPlayer"
msgstr "L'AnimationTree no té ruta assignada cap a un AnimationPlayer"
#: editor/plugins/root_motion_editor_plugin.cpp
-#, fuzzy
msgid "Path to AnimationPlayer is invalid"
msgstr "El camí cap a l'AnimationPlayer no és vàlid"
@@ -7751,7 +7723,6 @@ msgstr ""
"No s'hi poden afegir els nodes ja que l'escena no utilitza l'script '%s' ."
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Lookup Symbol"
msgstr "Cercar Símbol"
@@ -7864,7 +7835,6 @@ msgid "Contextual Help"
msgstr "Ajuda Contextual"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Toggle Bookmark"
msgstr "Commutar Marcador"
@@ -7873,9 +7843,8 @@ msgid "Go to Next Bookmark"
msgstr "Anar al marcador següent"
#: editor/plugins/script_text_editor.cpp
-#, fuzzy
msgid "Go to Previous Bookmark"
-msgstr "Anar al marcador anterior"
+msgstr "Anar al Marcador Anterior"
#: editor/plugins/script_text_editor.cpp
msgid "Remove All Bookmarks"
@@ -7919,9 +7888,8 @@ msgid "Shader"
msgstr "Shader"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
-#, fuzzy
msgid "This skeleton has no bones, create some children Bone2D nodes."
-msgstr "Aquest esquelet no té ossos, crea alguns nodes fill Bone2D."
+msgstr "Aquest esquelet no té ossos, crea alguns nodes Bone2D fills."
#: editor/plugins/skeleton_2d_editor_plugin.cpp
#, fuzzy
@@ -7929,9 +7897,8 @@ msgid "Create Rest Pose from Bones"
msgstr "Crea Punts d'Emissió des d'una Malla"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
-#, fuzzy
msgid "Set Rest Pose to Bones"
-msgstr "Estableix la postura de repòs als ossos"
+msgstr "Estableix la Postura de Repòs als Ossos"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
msgid "Skeleton2D"
@@ -7960,7 +7927,6 @@ msgid "Create physical skeleton"
msgstr "Crea esquelet físic"
#: editor/plugins/skeleton_ik_editor_plugin.cpp
-#, fuzzy
msgid "Play IK"
msgstr "Reproduir IK"
@@ -8252,7 +8218,6 @@ msgid "Cinematic Preview"
msgstr "Previsualització Cinemàtica"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Not available when using the GLES2 renderer."
msgstr "No disponible quan s'utilitza el renderitzador GLES2."
@@ -8304,13 +8269,13 @@ msgid ""
msgstr ""
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid ""
"Note: The FPS value displayed is the editor's framerate.\n"
"It cannot be used as a reliable indication of in-game performance."
msgstr ""
-"Nota: el valor FPS mostrat és la taxa de fotogrames de l'editor.\n"
-"No es pot utilitzar com una indicació fiable del rendiment en el joc."
+"Nota: El valor FPS que es mostra és el percentatge de fotogrames de "
+"l'editor.\n"
+"No es pot utilitzar com a indicació fiable del rendiment del joc."
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -8336,9 +8301,8 @@ msgid "Snap Nodes to Floor"
msgstr "Ajustar Nodes al Terra"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Couldn't find a solid floor to snap the selection to."
-msgstr "No ha pogut trobar un terra sòlid per ajustar la selecció."
+msgstr "No s'ha pogut trobar un sòl sòlid on ajustar la selecció."
#: editor/plugins/spatial_editor_plugin.cpp
#, fuzzy
@@ -8487,17 +8451,14 @@ msgid "Snap Settings"
msgstr "Configuració d'Ajustament"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Translate Snap:"
msgstr "Ajustament de Translació:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Rotate Snap (deg.):"
msgstr "Ajustament de Rotació (graus):"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Scale Snap (%):"
msgstr "Ajustament d'Escala (%):"
@@ -8588,9 +8549,8 @@ msgid "LightOccluder2D Preview"
msgstr "Crea un Polígon Oclusor"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Sprite is empty!"
-msgstr "El Sprite està buit!"
+msgstr "L'Sprite està buit!"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Can't convert a sprite using animation frames to mesh."
@@ -8623,9 +8583,8 @@ msgid "Create CollisionPolygon2D Sibling"
msgstr "Crea un Polígon de Navegació"
#: editor/plugins/sprite_editor_plugin.cpp
-#, fuzzy
msgid "Invalid geometry, can't create light occluder."
-msgstr "La geometria no és vàlida, no es pot crear oclusor de llum."
+msgstr "La geometria no és vàlida; no es pot crear un oclusor de llum."
#: editor/plugins/sprite_editor_plugin.cpp
#, fuzzy
@@ -8657,12 +8616,10 @@ msgid "Settings:"
msgstr "Configuració:"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "No Frames Selected"
-msgstr "No hi ha Fotogrames Seleccionats"
+msgstr "No s'ha seleccionat cap fotograma"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Add %d Frame(s)"
msgstr "Afegir %d Fotograma(es)"
@@ -8729,9 +8686,8 @@ msgid "Add a Texture from File"
msgstr "Afegir Textura des de Fitxer"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Add Frames from a Sprite Sheet"
-msgstr "Afegir fotogrames des d'una fulla de Sprites"
+msgstr "Afegir fotogrames des d'un full d'Sprites"
#: editor/plugins/sprite_frames_editor_plugin.cpp
msgid "Insert Empty (Before)"
@@ -8750,7 +8706,6 @@ msgid "Move (After)"
msgstr "Mou (Després)"
#: editor/plugins/sprite_frames_editor_plugin.cpp
-#, fuzzy
msgid "Select Frames"
msgstr "Seleccionar Fotogrames"
@@ -8789,9 +8744,8 @@ msgid "Snap Mode:"
msgstr "Mode d'ajustament:"
#: editor/plugins/texture_region_editor_plugin.cpp
-#, fuzzy
msgid "Pixel Snap"
-msgstr "Ajustar amb els Píxels"
+msgstr "Ajustament de Píxels"
#: editor/plugins/texture_region_editor_plugin.cpp
msgid "Grid Snap"
@@ -9310,9 +9264,8 @@ msgid ""
msgstr ""
#: editor/plugins/theme_editor_preview.cpp
-#, fuzzy
msgid "Toggle Button"
-msgstr "Botó de commutació"
+msgstr "Botó de Commutació"
#: editor/plugins/theme_editor_preview.cpp
msgid "Disabled Button"
@@ -9391,7 +9344,6 @@ msgid "Editable Item"
msgstr "Element Editable"
#: editor/plugins/theme_editor_preview.cpp
-#, fuzzy
msgid "Subtree"
msgstr "Subarbre"
@@ -9421,9 +9373,8 @@ msgid "Erase Selection"
msgstr "Elimina la Selecció"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Fix Invalid Tiles"
-msgstr "Arreglar Rajoles no Valides"
+msgstr "Arreglar Tiles no vàlides"
#: editor/plugins/tile_map_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
@@ -9468,9 +9419,8 @@ msgid "Enable Priority"
msgstr "Habilitar Prioritat"
#: editor/plugins/tile_map_editor_plugin.cpp
-#, fuzzy
msgid "Filter tiles"
-msgstr "Filtrat de Fitxers"
+msgstr "Filtrar tiles"
#: editor/plugins/tile_map_editor_plugin.cpp
msgid "Give a TileSet resource to this TileMap to use its tiles."
@@ -9523,14 +9473,12 @@ msgid "Clear Transform"
msgstr "Restablir Transformació"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Add Texture(s) to TileSet."
-msgstr "Afegeix Nodes des d'Arbre."
+msgstr "Afegir Textura(es) al TileSet"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Remove selected Texture from TileSet."
-msgstr "Elimineu la textura seleccionada de TileSet."
+msgstr "Eliminar la textura seleccionada del TileSet."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Create from Scene"
@@ -9559,18 +9507,16 @@ msgid "Next Coordinate"
msgstr "Coordenada Següent"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Select the next shape, subtile, or Tile."
-msgstr "Seleccioneu la forma, sub-rajola o rajola següent."
+msgstr "Seleccioneu la següent forma, subtile o Tile."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Previous Coordinate"
msgstr "Coordenada Anterior"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Select the previous shape, subtile, or Tile."
-msgstr "Seleccioneu la forma, sub-rajola o rajola anterior."
+msgstr "Seleccioneu la forma, el subtile o el Tile anterior."
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -9648,12 +9594,10 @@ msgid "Copy bitmask."
msgstr "Copiar màscara de bits."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Paste bitmask."
msgstr "Enganxar màscara de bits."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Erase bitmask."
msgstr "Esborrar màscara de bits."
@@ -9681,9 +9625,8 @@ msgid "Delete Selected Shape"
msgstr "Elimina Seleccionats"
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Keep polygon inside region Rect."
-msgstr "Mantenir polígon dins de la regió Rect."
+msgstr "Mantenir el polígon dins de la regió Rect."
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Enable snap and show grid (configurable via the Inspector)."
@@ -9737,9 +9680,8 @@ msgstr ""
"Clica en una altra Peça per a editar-lo."
#: editor/plugins/tile_set_editor_plugin.cpp
-#, fuzzy
msgid "Delete selected Rect."
-msgstr "Suprimir Rectangle seleccionat."
+msgstr "Suprimir el Rect seleccionat."
#: editor/plugins/tile_set_editor_plugin.cpp
#, fuzzy
@@ -10385,7 +10327,6 @@ msgid "Returns the arc-sine of the parameter."
msgstr "Retorna l'arc sinus del paràmetre."
#: editor/plugins/visual_shader_editor_plugin.cpp
-#, fuzzy
msgid "Returns the inverse hyperbolic sine of the parameter."
msgstr "Retorna el sinus hiperbòlic invers del paràmetre."
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 572c2afb2f..9f6f7ee0bf 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -72,13 +72,14 @@
# Philipp Wabnitz <philipp.wabnitz@s2011.tu-chemnitz.de>, 2021.
# jmih03 <joerni@mail.de>, 2021.
# Dominik Moos <dominik.moos@protonmail.com>, 2021.
+# Zae Chao <zaevi@live.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-09-22 20:30+0000\n"
-"Last-Translator: So Wieso <sowieso@dukun.de>\n"
+"PO-Revision-Date: 2021-10-23 10:13+0000\n"
+"Last-Translator: Zae Chao <zaevi@live.com>\n"
"Language-Team: German <https://hosted.weblate.org/projects/godot-engine/"
"godot/de/>\n"
"Language: de\n"
@@ -2487,9 +2488,8 @@ msgstr ""
"(Instanzen oder Vererbungen) nicht erfüllt."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Konvertierte Textur konnte nicht gespeichert werden:"
+msgstr "Eine oder mehrere Szenen konnten nicht gespeichert werden!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2632,7 +2632,7 @@ msgstr "Änderungen in ‚%s‘ vor dem Schließen speichern?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "%s existiert nicht mehr! Bitte anderen Ort zum Speichern wählen."
#: editor/editor_node.cpp
msgid ""
@@ -4491,6 +4491,12 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Es existieren ausstehende Änderungen die noch nicht angewandt wurden. Um "
+"Änderungen der Importoptionen anzuwenden, bitte den Reimportieren-Knopf "
+"klicken.\n"
+"Eine andere Ressource in der Dateisystemleiste auszuwählen, ohne zuvor den "
+"Reimportieren-Knopf zu betätigen, verwirft sämtliche ausstehende Änderungen "
+"der Importoptionen."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -5775,7 +5781,7 @@ msgstr "%d CanvasItems verschieben"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Move CanvasItem \"%s\" to (%d, %d)"
-msgstr "CanvasItem „%s“ zu (%d, d%) verschieben"
+msgstr "CanvasItem „%s“ zu (%d, %d) verschieben"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
@@ -7476,12 +7482,10 @@ msgid "Move Down"
msgstr "Schiebe runter"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Nächstes Skript"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Vorheriges Skript"
@@ -7901,9 +7905,8 @@ msgid "Left Orthogonal"
msgstr "Links orthogonal"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspektivisch"
+msgstr "Linke Perspektive"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8265,24 +8268,23 @@ msgstr "Sicht von rechts"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Orbitsicht unten"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Orbitsicht links"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Orbitsicht rechts"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Sicht von vorne"
+msgstr "Orbitsicht oben"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Orbitsicht 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -14651,6 +14653,10 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Sehr kurze Schaltzeiten (< 0,05 Sekunden) können instabile Ergebnisse "
+"abhängig von der Bildfrequenz liefern.\n"
+"Für sehr kurze Schaltzeiten wird empfohlen, statt eines Timers, die "
+"›process‹-Schleife eines Skripts zu benutzen."
#: scene/main/viewport.cpp
msgid ""
@@ -14666,12 +14672,12 @@ msgstr ""
"irgendeinem Node zum Anzeigen zugewiesen werden."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
-"Die Größe des Viewports muss größer als 0 sein um etwas rendern zu können."
+"Die Größe des Viewports muss mindestes 2 Pixel in beiden Dimensionen "
+"betragen um überhaupt irgendetwas rendern zu können."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 522575a8fc..bc314e8294 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -75,8 +75,8 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-10-02 10:08+0000\n"
-"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n"
+"PO-Revision-Date: 2021-10-23 10:13+0000\n"
+"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
"Language: es\n"
@@ -2483,9 +2483,8 @@ msgstr ""
"herencias) no se pudieron resolver."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "No se pudo guardar la textura convertida:"
+msgstr "¡No se ha podido guardar una o varias escenas!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2630,6 +2629,7 @@ msgstr "¿Guardar cambios de '%s' antes de cerrar?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
msgstr ""
+"¡%s ya no existe! Por favor, especifica una nueva ubicación de guardado."
#: editor/editor_node.cpp
msgid ""
@@ -4491,6 +4491,11 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Tienes cambios pendientes que aún no se han aplicado. Haz clic en Reimportar "
+"para aplicar los cambios realizados en las opciones de importación.\n"
+"Si seleccionas otro recurso en el dock Sistema de Archivos sin hacer clic en "
+"Reimportar primero, se descartarán los cambios realizados en el dock "
+"Importar."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7479,14 +7484,12 @@ msgid "Move Down"
msgstr "Bajar"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
-msgstr "Script siguiente"
+msgstr "Siguiente Script"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
-msgstr "Script anterior"
+msgstr "Script Anterior"
#: editor/plugins/script_editor_plugin.cpp
msgid "File"
@@ -7902,9 +7905,8 @@ msgid "Left Orthogonal"
msgstr "Ortogonal Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspectiva"
+msgstr "Perspectiva Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8263,24 +8265,23 @@ msgstr "Vista Derecha"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Vista de Órbita Inferior"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Vista de Órbita Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Vista de Órbita Derecha"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Vista Frontal"
+msgstr "Vista de Órbita Superior"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Vista de Órbita 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -13528,11 +13529,11 @@ msgstr ""
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
-msgstr "Firma de depuración %s..."
+msgstr "Firmando %s debug..."
#: platform/android/export/export_plugin.cpp
msgid "Signing release %s..."
-msgstr "Firmando liberación %s..."
+msgstr "Firmando %s release..."
#: platform/android/export/export_plugin.cpp
msgid "Could not find keystore, unable to export."
@@ -14640,6 +14641,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Los tiempos de espera del temporizador muy bajos (< 0,05 segundos) pueden "
+"comportarse de manera significativamente diferente dependiendo de la "
+"velocidad de fotogramas renderizados o de la física.\n"
+"Considera la posibilidad de utilizar un bucle en process dentro del script "
+"en lugar de depender de un Timer para tiempos de espera muy bajos."
#: scene/main/viewport.cpp
msgid ""
@@ -14655,13 +14661,12 @@ msgstr ""
"nodo para que se muestre."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
-"El tamaño del Viewport debe ser mayor que 0 para poder renderizar cualquier "
-"cosa."
+"El tamaño del Viewport debe ser mayor o igual a 2 píxeles en ambas "
+"dimensiones para renderizar cualquier cosa."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 76afb25668..dbff18af4e 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -24,7 +24,7 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-10-10 10:18+0000\n"
+"PO-Revision-Date: 2021-10-23 10:13+0000\n"
"Last-Translator: Lisandro Lorea <lisandrolorea@gmail.com>\n"
"Language-Team: Spanish (Argentina) <https://hosted.weblate.org/projects/"
"godot-engine/godot/es_AR/>\n"
@@ -2427,9 +2427,8 @@ msgstr ""
"dependencias (instancias o herencia)."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "No se pudo guardar la textura convertida:"
+msgstr "¡No se ha podido guardar una o varias escenas!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2575,6 +2574,7 @@ msgstr "Guardar cambios a '%s' antes de cerrar?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
msgstr ""
+"¡%s ya no existe! Por favor, especificá una nueva ubicación de guardado."
#: editor/editor_node.cpp
msgid ""
@@ -3881,7 +3881,7 @@ msgstr "Abrir Carpeta"
#: editor/export_template_manager.cpp
msgid "Open the folder containing installed templates for the current version."
msgstr ""
-"Abra la carpeta que contiene las plantillas instaladas para la versión "
+"Abrir la carpeta que contiene las plantillas instaladas para la versión "
"actual."
#: editor/export_template_manager.cpp
@@ -4433,6 +4433,11 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Tenés cambios pendientes que aún no se han aplicado. Hacé clic en Reimportar "
+"para aplicar los cambios realizados en las opciones de importación.\n"
+"Si seleccionás otro recurso en el dock Sistema de Archivos sin hacer clic en "
+"Reimportar primero, se descartarán los cambios realizados en el dock "
+"Importar."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -5924,7 +5929,7 @@ msgstr "Arrastrar: Rotar el nodo seleccionado alrededor del pivote."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Alt+Drag: Move selected node."
-msgstr "Alt+Arrastrar: Mover el nodo seleccionado"
+msgstr "Alt+Arrastrar: Mover el nodo seleccionado."
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "V: Set selected node's pivot position."
@@ -7268,16 +7273,15 @@ msgstr "Generar Puntos en la Room"
#: editor/plugins/room_manager_editor_plugin.cpp
msgid "Generate Points"
-msgstr "Conteo de Puntos Generados:"
+msgstr "Generar puntos"
#: editor/plugins/room_manager_editor_plugin.cpp
msgid "Flip Portal"
msgstr "Invertir Portal"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Set Transform"
-msgstr "Reestablecer Transform"
+msgstr "Transform de Occluder Set"
#: editor/plugins/room_manager_editor_plugin.cpp
msgid "Center Node"
@@ -7417,14 +7421,12 @@ msgid "Move Down"
msgstr "Bajar"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
-msgstr "Script siguiente"
+msgstr "Script Siguiente"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
-msgstr "Script anterior"
+msgstr "Script Anterior"
#: editor/plugins/script_editor_plugin.cpp
msgid "File"
@@ -7840,9 +7842,8 @@ msgid "Left Orthogonal"
msgstr "Ortogonal Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspectiva"
+msgstr "Perspectiva Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8201,24 +8202,23 @@ msgstr "Vista Derecha"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Orbitar Vista Hacia Abajo"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Orbitar Vista Hacia La Izquierda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Orbitar Vista Hacia La Derecha"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Vista Frontal"
+msgstr "Orbitar Vista Hacia Arriba"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Orbitar Vista 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -8716,7 +8716,7 @@ msgstr "Seleccione todos los elementos visibles de color y sus datos."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Deselect all visible color items."
-msgstr "Quitar selección a todos los elementos visibles de color."
+msgstr "Quitar selección a todos los items de color visibles."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all visible constant items."
@@ -8724,11 +8724,11 @@ msgstr "Seleccionar todos elementos constant visibles."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all visible constant items and their data."
-msgstr "Seleccionar todos los elementos constant visibles y sus datos."
+msgstr "Seleccionar todos los items visibles constantes y sus datos."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Deselect all visible constant items."
-msgstr "Deseleccionar todos los elementos constant visibles."
+msgstr "Quitar selección a todos los items visibles constantes."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all visible font items."
@@ -8736,7 +8736,7 @@ msgstr "Seleccionar todos los elementos font visibles."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all visible font items and their data."
-msgstr "Seleccionar todos los elementos font visibles y sus datos."
+msgstr "Seleccionar todos los items visibles y sus datos."
#: editor/plugins/theme_editor_plugin.cpp
msgid "Deselect all visible font items."
@@ -11820,6 +11820,11 @@ msgid ""
"FileSystem dock context menu\n"
"or create an inherited scene using Scene > New Inherited Scene... instead."
msgstr ""
+"No se puede guardar la rama del nodo raíz como una escena instanciada.\n"
+"Para crear una copia editable de la escena actual, duplicala usando el menú "
+"contextual del dock Sistema de Archivos\n"
+"o crea una escena heredada usando Escena > Nueva Escena Heredada... en su "
+"lugar."
#: editor/scene_tree_dock.cpp
msgid ""
@@ -11827,6 +11832,10 @@ msgid ""
"To create a variation of a scene, you can make an inherited scene based on "
"the instanced scene using Scene > New Inherited Scene... instead."
msgstr ""
+"No se puede guardar la rama de una escena ya instanciada.\n"
+"Para crear una variación de una escena, puedes hacer una escena heredada "
+"basada en la escena instanciada usando Escena > Nueva Escena Heredada... en "
+"su lugar."
#: editor/scene_tree_dock.cpp
msgid "Save New Scene As..."
@@ -12488,24 +12497,20 @@ msgid "Change Ray Shape Length"
msgstr "Cambiar Largo de Shape Rayo"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Room Point Position"
-msgstr "Setear Posición de Punto de Curva"
+msgstr "Establecer Posición del Room Point"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Portal Point Position"
-msgstr "Setear Posición de Punto de Curva"
+msgstr "Establecer Posición del Portal Point"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Radius"
-msgstr "Cambiar Radio de Shape Cilindro"
+msgstr "Establecer Radio de la Esfera de Oclusión"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Position"
-msgstr "Setear Posición de Entrada de Curva"
+msgstr "Establecer Posición de la Esfera de Oclusión"
#: modules/csg/csg_gizmos.cpp
msgid "Change Cylinder Radius"
@@ -12619,14 +12624,12 @@ msgid "Object can't provide a length."
msgstr "El objeto no puede proveer un largo."
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
-#, fuzzy
msgid "Export Mesh GLTF2"
-msgstr "Exportar Librería de Meshes"
+msgstr "Exportar Malla GLTF2"
#: modules/gltf/editor_scene_exporter_gltf_plugin.cpp
-#, fuzzy
msgid "Export GLTF..."
-msgstr "Exportar..."
+msgstr "Exportar GLTF..."
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Next Plane"
@@ -12669,9 +12672,8 @@ msgid "GridMap Paint"
msgstr "Pintar GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
-#, fuzzy
msgid "GridMap Selection"
-msgstr "Llenar Selección en GridMap"
+msgstr "Selección de GridMap"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Grid Map"
@@ -12794,9 +12796,8 @@ msgid "Class name can't be a reserved keyword"
msgstr "El nombre de la clase no puede ser una palabra reservada"
#: modules/mono/csharp_script.cpp
-#, fuzzy
msgid "Build Solution"
-msgstr "Llenar la Selección"
+msgstr "Construir Solución"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -12928,14 +12929,12 @@ msgid "Add Output Port"
msgstr "Agregar Puerto de Salida"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Port Type"
-msgstr "Cambiar Tipo"
+msgstr "Cambiar Tipo de Puerto"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Change Port Name"
-msgstr "Cambiar nombre del puerto de entrada"
+msgstr "Cambiar Nombre de Puerto"
#: modules/visual_script/visual_script_editor.cpp
msgid "Override an existing built-in function."
@@ -13050,9 +13049,8 @@ msgid "Add Preload Node"
msgstr "Agregar Nodo Preload"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Add Node(s)"
-msgstr "Agregar Nodo"
+msgstr "Agregar Nodo(s)"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Node(s) From Tree"
@@ -13319,37 +13317,31 @@ msgstr "Seleccionar dispositivo de la lista"
#: platform/android/export/export_plugin.cpp
msgid "Running on %s"
-msgstr ""
+msgstr "Ejecutando en %s"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exporting APK..."
-msgstr "Exportar Todo"
+msgstr "Exportar APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Uninstalling..."
-msgstr "Desinstalar"
+msgstr "Desinstalando..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Installing to device, please wait..."
-msgstr "Cargando, esperá, por favor..."
+msgstr "Instalando en el dispositivo, espera por favor..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not install to device: %s"
-msgstr "No se pudo instanciar la escena!"
+msgstr "No se pudo instalar en el dispositivo: %s"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Running on device..."
-msgstr "Ejecutando Script Personalizado..."
+msgstr "Ejecutando en el dispositivo..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not execute on device."
-msgstr "No se pudo crear la carpeta."
+msgstr "No se ha podido ejecutar en el dispositivo."
#: platform/android/export/export_plugin.cpp
msgid "Unable to find the 'apksigner' tool."
@@ -13460,40 +13452,38 @@ msgid ""
"directory.\n"
"The resulting %s is unsigned."
msgstr ""
+"No se ha encontrado 'apksigner'.\n"
+"Por favor, comprobá que el comando esté disponible en el directorio Android "
+"SDK build-tools.\n"
+"El %s resultante está sin firmar."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
-msgstr ""
+msgstr "Firmando %s debug..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Signing release %s..."
-msgstr ""
-"Examinando Archivos,\n"
-"Aguardá, por favor."
+msgstr "Firmando %s release..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not find keystore, unable to export."
-msgstr "No se pudo abrir la plantilla para exportar:"
+msgstr "No se pudo encontrar la keystore, no se puedo exportar."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' returned with error #%d"
-msgstr ""
+msgstr "'apksigner' ha retornado con error #%d"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Verifying %s..."
-msgstr "Agregando %s..."
+msgstr "Verificando %s..."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' verification of %s failed."
-msgstr ""
+msgstr "La verificación de 'apksigner' de %s ha fallado."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exporting for Android"
-msgstr "Exportar Todo"
+msgstr "Exportando para Android"
#: platform/android/export/export_plugin.cpp
msgid "Invalid filename! Android App Bundle requires the *.aab extension."
@@ -13510,7 +13500,7 @@ msgstr "¡Nombre de archivo inválido! Android APK requiere la extensión *.apk.
#: platform/android/export/export_plugin.cpp
msgid "Unsupported export format!\n"
-msgstr ""
+msgstr "¡Formato de exportación no soportado!\n"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -13538,16 +13528,17 @@ msgstr ""
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name"
msgstr ""
+"No se pudieron sobrescribir los archivos res://android/build/res/*.xml con "
+"el nombre del proyecto"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files to gradle project\n"
-msgstr "No se pudo obtener project.godot en la ruta de proyecto."
+msgstr ""
+"No se pudieron exportar los archivos del proyecto a un proyecto gradle\n"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not write expansion package file!"
-msgstr "No se pudo escribir el archivo:"
+msgstr "¡No se pudo escribir el archivo del paquete de expansión!"
#: platform/android/export/export_plugin.cpp
msgid "Building Android Project (gradle)"
@@ -13575,21 +13566,20 @@ msgstr ""
"directorio del proyecto de gradle para ver los resultados."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: %s"
-msgstr "No se encontró la animación: '%s'"
+msgstr "Paquete no encontrado:% s"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Creating APK..."
-msgstr "Creando contornos..."
+msgstr "Creando APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid ""
"Could not find template APK to export:\n"
"%s"
-msgstr "No se pudo abrir la plantilla para exportar:"
+msgstr ""
+"No se pudo encontrar la plantilla APK para exportar:\n"
+"%s"
#: platform/android/export/export_plugin.cpp
msgid ""
@@ -13598,24 +13588,26 @@ msgid ""
"Please build a template with all required libraries, or uncheck the missing "
"architectures in the export preset."
msgstr ""
+"Bibliotecas faltantes en la plantilla de exportación para las arquitecturas "
+"seleccionadas: %s.\n"
+"Por favor, construya una plantilla con todas las bibliotecas necesarias, o "
+"desmarque las arquitecturas faltantes en el preset de exportación."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Adding files..."
-msgstr "Agregando %s..."
+msgstr "Agregando archivos..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not export project files"
-msgstr "No se pudo escribir el archivo:"
+msgstr "No se pudieron exportar los archivos del proyecto"
#: platform/android/export/export_plugin.cpp
msgid "Aligning APK..."
-msgstr ""
+msgstr "Alineando APK..."
#: platform/android/export/export_plugin.cpp
msgid "Could not unzip temporary unaligned APK."
-msgstr ""
+msgstr "No se pudo descomprimir el APK temporal no alineado."
#: platform/iphone/export/export.cpp platform/osx/export/export.cpp
msgid "Identifier is missing."
@@ -13663,45 +13655,40 @@ msgid "Could not write file:"
msgstr "No se pudo escribir el archivo:"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read file:"
-msgstr "No se pudo escribir el archivo:"
+msgstr "No se pudo leer el archivo:"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not read HTML shell:"
-msgstr "No se pudo leer el shell HTML personalizado:"
+msgstr "No se pudo leer el shell HTML:"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Could not create HTTP server directory:"
-msgstr "No se pudo crear la carpeta."
+msgstr "No se pudo crear el directorio del servidor HTTP:"
#: platform/javascript/export/export.cpp
-#, fuzzy
msgid "Error starting HTTP server:"
-msgstr "Error al guardar escena."
+msgstr "Error al iniciar el servidor HTTP:"
#: platform/osx/export/export.cpp
-#, fuzzy
msgid "Invalid bundle identifier:"
-msgstr "Identificador inválido:"
+msgstr "Identificador de paquete no válido:"
#: platform/osx/export/export.cpp
msgid "Notarization: code signing required."
-msgstr ""
+msgstr "Notarización: se requiere firma de código."
#: platform/osx/export/export.cpp
msgid "Notarization: hardened runtime required."
-msgstr ""
+msgstr "Notarización: se requiere hardened runtime."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID name not specified."
-msgstr ""
+msgstr "Notarización: nombre de ID de Apple no especificado."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID password not specified."
-msgstr ""
+msgstr "Notarización: contraseña de ID de Apple no especificada."
#: platform/uwp/export/export.cpp
msgid "Invalid package short name."
@@ -14146,6 +14133,9 @@ msgid ""
"longer has any effect.\n"
"To remove this warning, disable the GIProbe's Compress property."
msgstr ""
+"La propiedad Compress de GIProbe ha quedado obsoleta debido a errores "
+"conocidos y ya no tiene ningún efecto.\n"
+"Para eliminar esta advertencia, desactiva la propiedad Compress de GIProbe."
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
@@ -14168,11 +14158,11 @@ msgstr ""
#: scene/3d/occluder.cpp
msgid "No shape is set."
-msgstr ""
+msgstr "No se ha establecido ninguna forma."
#: scene/3d/occluder.cpp
msgid "Only uniform scales are supported."
-msgstr ""
+msgstr "Sólo se admiten escalas uniformes."
#: scene/3d/particles.cpp
msgid ""
@@ -14243,15 +14233,15 @@ msgstr "El nodo A y el nodo B deben ser diferentes PhysicsBody"
#: scene/3d/portal.cpp
msgid "The RoomManager should not be a child or grandchild of a Portal."
-msgstr ""
+msgstr "El RoomManager no debe ser hijo o nieto de un Portal."
#: scene/3d/portal.cpp
msgid "A Room should not be a child or grandchild of a Portal."
-msgstr ""
+msgstr "Una Room no debe ser hijo o nieto de un Portal."
#: scene/3d/portal.cpp
msgid "A RoomGroup should not be a child or grandchild of a Portal."
-msgstr ""
+msgstr "Un RoomGroup no debe ser hijo o nieto de un Portal."
#: scene/3d/remote_transform.cpp
msgid ""
@@ -14263,79 +14253,98 @@ msgstr ""
#: scene/3d/room.cpp
msgid "A Room cannot have another Room as a child or grandchild."
-msgstr ""
+msgstr "Una Room no puede tener otra Room como hija o nieta."
#: scene/3d/room.cpp
msgid "The RoomManager should not be placed inside a Room."
-msgstr ""
+msgstr "El RoomManager no debe ubicarse dentro de una Room."
#: scene/3d/room.cpp
msgid "A RoomGroup should not be placed inside a Room."
-msgstr ""
+msgstr "Un RoomGroup no debe colocarse dentro de una Room."
#: scene/3d/room.cpp
msgid ""
"Room convex hull contains a large number of planes.\n"
"Consider simplifying the room bound in order to increase performance."
msgstr ""
+"El cuerpo convexo de la room contiene un gran número de planos.\n"
+"Considera la posibilidad de simplificar los límites de la room para aumentar "
+"el rendimiento."
#: scene/3d/room_group.cpp
msgid "The RoomManager should not be placed inside a RoomGroup."
-msgstr ""
+msgstr "El RoomManager no debe colocarse dentro de un RoomGroup."
#: scene/3d/room_manager.cpp
msgid "The RoomList has not been assigned."
-msgstr ""
+msgstr "La RoomList no ha sido asignada."
#: scene/3d/room_manager.cpp
msgid "The RoomList node should be a Spatial (or derived from Spatial)."
-msgstr ""
+msgstr "El nodo RoomList debe ser un Spatial (o derivado de Spatial)."
#: scene/3d/room_manager.cpp
msgid ""
"Portal Depth Limit is set to Zero.\n"
"Only the Room that the Camera is in will render."
msgstr ""
+"El Límite de Profundidad del Portal está ajustado a cero.\n"
+"Sólo se renderizará la room en la que se encuentra la cámara."
#: scene/3d/room_manager.cpp
msgid "There should only be one RoomManager in the SceneTree."
-msgstr ""
+msgstr "Sólo debe haber un RoomManager en el SceneTree."
#: scene/3d/room_manager.cpp
msgid ""
"RoomList path is invalid.\n"
"Please check the RoomList branch has been assigned in the RoomManager."
msgstr ""
+"La ruta del RoomList no es válida.\n"
+"Por favor, comprueba que la rama de la RoomList ha sido asignada al "
+"RoomManager."
#: scene/3d/room_manager.cpp
msgid "RoomList contains no Rooms, aborting."
-msgstr ""
+msgstr "La RoomList no contiene Rooms, abortando."
#: scene/3d/room_manager.cpp
msgid "Misnamed nodes detected, check output log for details. Aborting."
msgstr ""
+"Nodos con nombres incorrectos detectados, comprueba la salida del Log para "
+"más detalles. Abortando."
#: scene/3d/room_manager.cpp
msgid "Portal link room not found, check output log for details."
msgstr ""
+"No se encuentra Portal link room, comprueba la salida del Log para más "
+"detalles."
#: scene/3d/room_manager.cpp
msgid ""
"Portal autolink failed, check output log for details.\n"
"Check the portal is facing outwards from the source room."
msgstr ""
+"Fallo en el Portal autolink, comprueba la salida del Log para más detalles.\n"
+"Comprueba si el portal está mirando hacia fuera de la room de origen."
#: scene/3d/room_manager.cpp
msgid ""
"Room overlap detected, cameras may work incorrectly in overlapping area.\n"
"Check output log for details."
msgstr ""
+"Detectada superposición de la Room, las cámaras pueden funcionar "
+"incorrectamente en las zonas donde hay superposición.\n"
+"Comrpueba la salida del Log para más detalles."
#: scene/3d/room_manager.cpp
msgid ""
"Error calculating room bounds.\n"
"Ensure all rooms contain geometry or manual bounds."
msgstr ""
+"Error al calcular los límites de la room.\n"
+"Asegurate de que todas las rooms contengan geometría o límites manuales."
#: scene/3d/soft_body.cpp
msgid "This body will be ignored until you set a mesh."
@@ -14401,7 +14410,7 @@ msgstr "No se encontró la animación: '%s'"
#: scene/animation/animation_player.cpp
msgid "Anim Apply Reset"
-msgstr ""
+msgstr "Aplicar Reset de Animación"
#: scene/animation/animation_tree.cpp
msgid "In node '%s', invalid animation: '%s'."
@@ -14510,6 +14519,10 @@ msgid ""
"The GLES2 backend is currently in use, so these modes will act like Stretch "
"instead."
msgstr ""
+"Las opciones Tile y Tile Fit para las propiedades Axis Stretch sólo son "
+"efectivas cuando se utiliza el backend de renderizado GLES3.\n"
+"El backend GLES2 está actualmente en uso, por lo que estos modos actuarán "
+"como Stretch en su lugar."
#: scene/gui/popup.cpp
msgid ""
@@ -14554,6 +14567,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Los tiempos de espera del temporizador muy bajos (< 0,05 segundos) pueden "
+"comportarse de manera significativamente diferente dependiendo de la "
+"velocidad de fotogramas renderizados o de la física.\n"
+"Considera la posibilidad de utilizar un bucle en process dentro del script "
+"en lugar de depender de un Timer para tiempos de espera muy bajos."
#: scene/main/viewport.cpp
msgid ""
@@ -14568,15 +14586,16 @@ msgstr ""
"textura interna a algún otro nodo para mostrar."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
-msgstr "El tamaño del viewport debe ser mayor a 0 para poder renderizar."
+msgstr ""
+"El tamaño del Viewport debe ser mayor o igual a 2 píxeles en ambas "
+"dimensiones para renderizar cualquier cosa."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
-msgstr ""
+msgstr "Establecer Esferas OccluderShapeSphere"
#: scene/resources/visual_shader_nodes.cpp
msgid ""
@@ -14599,25 +14618,29 @@ msgid "Invalid comparison function for that type."
msgstr "Función de comparación inválida para este tipo."
#: servers/visual/shader_language.cpp
-#, fuzzy
msgid "Varying may not be assigned in the '%s' function."
-msgstr "Solo se pueden asignar variaciones en funciones de vértice."
+msgstr "No se pueden asignar varyings a la función '%s'."
#: servers/visual/shader_language.cpp
msgid ""
"Varyings which assigned in 'vertex' function may not be reassigned in "
"'fragment' or 'light'."
msgstr ""
+"Las varyings que fueron asignadas en una función 'vertex' no pueden ser "
+"reasignadas en 'fragment' o 'light'."
#: servers/visual/shader_language.cpp
msgid ""
"Varyings which assigned in 'fragment' function may not be reassigned in "
"'vertex' or 'light'."
msgstr ""
+"Las varyings que fueron asignadas en una función 'fragment' no pueden ser "
+"reasignadas en 'vertex' o 'light'."
#: servers/visual/shader_language.cpp
msgid "Fragment-stage varying could not been accessed in custom function!"
msgstr ""
+"¡No se pudo acceder a la fragment-stage varying en la función personalizada!"
#: servers/visual/shader_language.cpp
msgid "Assignment to function."
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index c300e21510..e61aa0a6c7 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -363,7 +363,7 @@ msgstr "حذ٠ترک انیمشین"
#. TRANSLATORS: %s will be replaced by a phrase describing the target of track.
#: editor/animation_track_editor.cpp
msgid "Create NEW track for %s and insert key?"
-msgstr "یک ترک جدید برای s% بساز و کلید را درج کن؟"
+msgstr "یک ترک جدید برای %s بساز و کلید را درج کن؟"
#: editor/animation_track_editor.cpp
msgid "Create %d NEW tracks and insert keys?"
@@ -904,11 +904,11 @@ msgstr "سیگنال:"
#: editor/connections_dialog.cpp
msgid "Connect '%s' to '%s'"
-msgstr "'s%' را به 's%' متصل کن"
+msgstr "'%s' را به '%s' متصل کن"
#: editor/connections_dialog.cpp
msgid "Disconnect '%s' from '%s'"
-msgstr "'s%' را از 's%' جدا کن"
+msgstr "'%s' را از '%s' جدا کن"
#: editor/connections_dialog.cpp
msgid "Disconnect all from signal: '%s'"
@@ -1024,7 +1024,7 @@ msgid ""
"Scene '%s' is currently being edited.\n"
"Changes will only take effect when reloaded."
msgstr ""
-"ویرایش صحنه 's%' شروع شده است.\n"
+"ویرایش صحنه '%s' شروع شده است.\n"
"تغییرات تنها وقتی جلوه گرند که از نو بارگیری شوند."
#: editor/dependency_editor.cpp
@@ -1032,7 +1032,7 @@ msgid ""
"Resource '%s' is in use.\n"
"Changes will only take effect when reloaded."
msgstr ""
-"منابع 's%' بکار Ø±ÙØªÙ‡â€ŒØ§Ù†Ø¯.\n"
+"منابع '%s' بکار Ø±ÙØªÙ‡â€ŒØ§Ù†Ø¯.\n"
"تغییرات تنها وقتی جلوه گرند که از نو بارگیری شوند."
#: editor/dependency_editor.cpp
@@ -1134,7 +1134,7 @@ msgstr "خطا در بارگذاری!"
#: editor/dependency_editor.cpp
msgid "Permanently delete %d item(s)? (No undo!)"
-msgstr "به طور دائمی تعداد 'd%' آیتم را حذ٠کند؟ (بدون undo !)"
+msgstr "به طور دائمی تعداد '%d' آیتم را حذ٠کند؟ (بدون undo !)"
#: editor/dependency_editor.cpp
msgid "Show Dependencies"
@@ -1519,7 +1519,7 @@ msgstr "کلمه کلیدی نمی تواند به عنوان یک نام خود
#: editor/editor_autoload_settings.cpp
msgid "Autoload '%s' already exists!"
-msgstr "بارگذاری خودکار 's%' هم اکنون موجود است!"
+msgstr "بارگذاری خودکار '%s' هم اکنون موجود است!"
#: editor/editor_autoload_settings.cpp
msgid "Rename Autoload"
@@ -4191,7 +4191,7 @@ msgstr ""
#: editor/groups_editor.cpp
#, fuzzy
msgid "Group name already exists."
-msgstr "بارگذاری خودکار 's%' هم اکنون موجود است!"
+msgstr "بارگذاری خودکار '%s' هم اکنون موجود است!"
#: editor/groups_editor.cpp
#, fuzzy
@@ -4670,7 +4670,7 @@ msgstr "گره انیمیشن"
#: editor/plugins/animation_blend_space_2d_editor.cpp
#, fuzzy
msgid "Triangle already exists."
-msgstr "بارگذاری خودکار 's%' هم اکنون موجود است!"
+msgstr "بارگذاری خودکار '%s' هم اکنون موجود است!"
#: editor/plugins/animation_blend_space_2d_editor.cpp
#, fuzzy
@@ -4875,7 +4875,7 @@ msgstr "نام نامعتبر."
#: editor/plugins/animation_player_editor_plugin.cpp
#, fuzzy
msgid "Animation name already exists!"
-msgstr "بارگذاری خودکار 's%' هم اکنون موجود است!"
+msgstr "بارگذاری خودکار '%s' هم اکنون موجود است!"
#: editor/plugins/animation_player_editor_plugin.cpp
#: editor/plugins/sprite_frames_editor_plugin.cpp
@@ -7606,7 +7606,7 @@ msgstr ""
#, fuzzy
msgid ""
"Missing connected method '%s' for signal '%s' from node '%s' to node '%s'."
-msgstr "'s%' را از 's%' جدا کن"
+msgstr "'%s' را از '%s' جدا کن"
#: editor/plugins/script_text_editor.cpp
msgid "[Ignore]"
@@ -11277,7 +11277,7 @@ msgstr ""
#: editor/project_settings_editor.cpp
#, fuzzy
msgid "An action with the name '%s' already exists."
-msgstr "بارگذاری خودکار 's%' هم اکنون موجود است!"
+msgstr "بارگذاری خودکار '%s' هم اکنون موجود است!"
#: editor/project_settings_editor.cpp
msgid "Rename Input Action Event"
@@ -13428,7 +13428,7 @@ msgstr "مسیر به یک نود نمیرسد!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
-msgstr "نام دارایی ایندکس نامعتبر 's%' در نود s%."
+msgstr "نام دارایی ایندکس نامعتبر '%s' در نود %s."
#: modules/visual_script/visual_script_nodes.cpp
msgid ": Invalid argument of type: "
@@ -14497,12 +14497,12 @@ msgstr ""
#: scene/animation/animation_tree.cpp
msgid "Invalid animation: '%s'."
-msgstr "انیمیشن نامعتبر: 's%'."
+msgstr "انیمیشن نامعتبر: '%s'."
#: scene/animation/animation_tree.cpp
#, fuzzy
msgid "Nothing connected to input '%s' of node '%s'."
-msgstr "'s%' را از 's%' جدا کن"
+msgstr "'%s' را از '%s' جدا کن"
#: scene/animation/animation_tree.cpp
msgid "No root AnimationNode for the graph is set."
@@ -14826,7 +14826,7 @@ msgstr "ثوابت قابل تغییر نیستند."
#~ msgstr "صحنه جدید"
#~ msgid "Replaced %d occurrence(s)."
-#~ msgstr "تعداد d% رخداد جایگزین شد."
+#~ msgstr "تعداد %d رخداد جایگزین شد."
#, fuzzy
#~ msgid "Brief Description"
@@ -15232,7 +15232,7 @@ msgstr "ثوابت قابل تغییر نیستند."
#~ "اسپرایت تنظیم شود تا کار کند."
#~ msgid "Method List For '%s':"
-#~ msgstr "لیست متد برای 's%' :"
+#~ msgstr "لیست متد برای '%s' :"
#~ msgid "Return:"
#~ msgstr "بازگشت:"
@@ -15273,7 +15273,7 @@ msgstr "ثوابت قابل تغییر نیستند."
#~ "SpatialSamplePlayer آهنگ را پخش کند."
#~ msgid "Replaced %d Ocurrence(s)."
-#~ msgstr "تعداد d% رخداد جایگزین شد."
+#~ msgstr "تعداد %d رخداد جایگزین شد."
#, fuzzy
#~ msgid "Create Android keystore"
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index d24317f129..a7dca1dd0d 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -17,7 +17,7 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-09-22 20:30+0000\n"
+"PO-Revision-Date: 2021-10-18 15:35+0000\n"
"Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n"
"Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/"
"godot/fi/>\n"
@@ -2407,9 +2407,8 @@ msgstr ""
"perintää) ei voida toteuttaa."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Aliprosessia ei voitu käynnistää!"
+msgstr "Yhtä tai useampaa skeneä ei voitu tallentaa!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2552,6 +2551,7 @@ msgstr "Tallennetaanko muutokset tiedostoon '%s' ennen sulkemista?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
msgstr ""
+"%s ei ole enää olemassa! Ole hyvä ja määrittele uusi tallennussijainti."
#: editor/editor_node.cpp
msgid ""
@@ -4390,6 +4390,11 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Sinulla on avoinna olevia muutoksia, joita ei ole vielä otettu käyttöön. "
+"Napsauta Tuo uudelleen ottaaksesi tuontivalinnoissa tehdyt muutokset "
+"käyttöön.\n"
+"Toisen resurssin valitseminen Tiedostojärjestelmä-telakassa ilman, että Tuo "
+"uudelleen on tehty hylkää Tuonti-telakassa tehdyt muutokset."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7366,12 +7371,10 @@ msgid "Move Down"
msgstr "Siirrä alas"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Seuraava skripti"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Edellinen skripti"
@@ -7788,9 +7791,8 @@ msgid "Left Orthogonal"
msgstr "Vasen ortogonaalinen"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspektiivi"
+msgstr "Vasen perspektiivi"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8149,24 +8151,23 @@ msgstr "Oikea näkymä"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Kiertoratanäkymä alas"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Kiertoratanäkymä vasemmalle"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Kiertoratanäkymä oikealle"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Etunäkymä"
+msgstr "Kiertoratanäkymä ylös"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Kiertoratanäkymä 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -14475,6 +14476,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Hyvin alhaiset ajastimen odotusajat (< 0,05 sekuntia) saattavat käyttäytyä "
+"merkittävästi eri tavoilla riippuen renderöinnin tai fysiikan "
+"päivitystaajuudesta.\n"
+"Harkitse skriptin prosessointisilmukan käyttöä Timer solmun hyvin alhaiseen "
+"odotusaikaan luottamisen sijaan."
#: scene/main/viewport.cpp
msgid ""
@@ -14489,12 +14495,12 @@ msgstr ""
"johonkin solmuun näkyväksi."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
-"Näyttöruudun koko on oltava suurempi kuin 0, jotta mitään renderöidään."
+"Näyttöruudun koko on oltava suurempi tai yhtä suuri kuin kaksi pikseliä "
+"kummassakin suunnassa, jotta mitään renderöidään."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index ea1e5dd57e..872b22322e 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -35,7 +35,7 @@
# Rémi Verschelde <rverschelde@gmail.com>, 2016-2017.
# Robin Arys <robinarys@hotmail.com>, 2017.
# Roger BR <drai_kin@hotmail.com>, 2016.
-# salty64 <cedric.arrabie@univ-pau.fr>, 2018, 2020.
+# salty64 <cedric.arrabie@univ-pau.fr>, 2018, 2020, 2021.
# Thomas Baijot <thomasbaijot@gmail.com>, 2016, 2019.
# Tommy Melançon-Roy <tommel1234@hotmail.com>, 2017-2018.
# Willow <theotimefd@aol.com>, 2018.
@@ -49,7 +49,7 @@
# Brice Lobet <tempo.data@gmail.com>, 2018.
# Florent Wijanto <f_wijanto@hotmail.com>, 2018.
# Olivier gareau <olivier.gareau@protonmail.com>, 2018.
-# Rémi Verschelde <akien@godotengine.org>, 2018, 2019, 2020.
+# Rémi Verschelde <akien@godotengine.org>, 2018, 2019, 2020, 2021.
# Rémi Bintein <reminus5@hotmail.fr>, 2018, 2019.
# Sylvain Corsini <sylvain.corsini@gmail.com>, 2018.
# Caye Pierre <pierrecaye@laposte.net>, 2019.
@@ -83,13 +83,14 @@
# Clément Topy <topy72.mine@gmail.com>, 2021.
# Cold <coldragon78@gmail.com>, 2021.
# Blackiris <divjvc@free.fr>, 2021.
+# Olivier Monnom <olivier.monnom@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-10-04 13:31+0000\n"
-"Last-Translator: Pierre Caye <pierrecaye@laposte.net>\n"
+"PO-Revision-Date: 2021-10-23 12:20+0200\n"
+"Last-Translator: salty64 <cedric.arrabie@univ-pau.fr>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -2500,9 +2501,8 @@ msgstr ""
"n'ont sans doute pas pu être satisfaites."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Impossible de démarrer le sous-processus !"
+msgstr "Impossible de sauver la (les) scènes(s) !"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2651,7 +2651,7 @@ msgstr "Sauvegarder les modifications effectuées à « %s » avant de quitt
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "%s n'existe plus ! Veuillez spécifier un nouvel endroit de sauvegarde."
#: editor/editor_node.cpp
msgid ""
@@ -2699,29 +2699,27 @@ msgstr "La scène actuelle n'est pas enregistrée. Ouvrir quand même ?"
#: editor/editor_node.cpp
msgid "Can't undo while mouse buttons are pressed."
-msgstr ""
+msgstr "Impossible d'annuler quand les boutons de la souris sont activés."
#: editor/editor_node.cpp
msgid "Nothing to undo."
-msgstr ""
+msgstr "Rien à annuler."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Undo: %s"
-msgstr "Annuler"
+msgstr "Annuler %s"
#: editor/editor_node.cpp
msgid "Can't redo while mouse buttons are pressed."
-msgstr ""
+msgstr "Impossible de rétablir quand les boutons de la souris sont activés."
#: editor/editor_node.cpp
msgid "Nothing to redo."
-msgstr ""
+msgstr "Rien à rétablir."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Redo: %s"
-msgstr "Refaire"
+msgstr "Refaire %s"
#: editor/editor_node.cpp
msgid "Can't reload a scene that was never saved."
@@ -2757,7 +2755,7 @@ msgstr "Quitter l'éditeur ?"
#: editor/editor_node.cpp
msgid "Open Project Manager?"
-msgstr "Ouvrir gestionnaire de projets ?"
+msgstr "Ouvrir le gestionnaire de projets ?"
#: editor/editor_node.cpp
msgid "Save & Quit"
@@ -3418,9 +3416,8 @@ msgid "Merge With Existing"
msgstr "Fusionner avec l'existant"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Apply MeshInstance Transforms"
-msgstr "Changer la transformation de l’animation"
+msgstr "Appliquer la transformation du MeshInstance"
#: editor/editor_node.cpp
msgid "Open & Run a Script"
@@ -3683,7 +3680,7 @@ msgstr ""
#: editor/editor_resource_picker.cpp
msgid "Quick Load"
-msgstr ""
+msgstr "Chargement rapide"
#: editor/editor_resource_picker.cpp editor/property_editor.cpp
msgid "Make Unique"
@@ -4519,6 +4516,12 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Vous avez des changements en attente qui n'ont pas encore été appliqués. "
+"Cliquez sur réimporter pour appliquer les changements des options "
+"d'importation\n"
+"Sélectionner une autre ressource dans le \"FileSystem dock\" sans cliquer "
+"sur réimport avant va annuler les changements faits dans le dock "
+"d'importation."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -5599,7 +5602,7 @@ msgstr "Dernier"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
-msgstr "All"
+msgstr "Tous"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "Search templates, projects, and demos"
@@ -5812,15 +5815,13 @@ msgstr "Déplacer le CanvasItem « %s » vers (%d, %d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Locked"
-msgstr "Verrouillage Sélectionné"
+msgstr "Verrouillé"
#: editor/plugins/canvas_item_editor_plugin.cpp
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Grouped"
-msgstr "Groupes"
+msgstr "Groupé"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid ""
@@ -6773,14 +6774,12 @@ msgid "Remove Selected Item"
msgstr "Supprimer l'élément sélectionné"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Import from Scene (Ignore Transforms)"
-msgstr "Importer depuis la scène"
+msgstr "Importer depuis la scène (Ignore les transformations)"
#: editor/plugins/mesh_library_editor_plugin.cpp
-#, fuzzy
msgid "Import from Scene (Apply Transforms)"
-msgstr "Importer depuis la scène"
+msgstr "Importer depuis la scène (Applique les transformations)"
#: editor/plugins/mesh_library_editor_plugin.cpp
msgid "Update from Scene"
@@ -7378,14 +7377,12 @@ msgid "Flip Portal"
msgstr "Retourner le Portal"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Set Transform"
-msgstr "Supprimer la transformation"
+msgstr "Définir la transformation pour l'occulteur"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Center Node"
-msgstr "Créer un nœud"
+msgstr "Centrer le nœud"
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "AnimationTree has no path set to an AnimationPlayer"
@@ -7521,12 +7518,10 @@ msgid "Move Down"
msgstr "Déplacer vers le bas"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Script suivant"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Script précédent"
@@ -7893,14 +7888,12 @@ msgid "Skeleton2D"
msgstr "Squelette 2D"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
-#, fuzzy
msgid "Reset to Rest Pose"
-msgstr "Assigner les os à la position de repos"
+msgstr "Remettre à la position de repos"
#: editor/plugins/skeleton_2d_editor_plugin.cpp
-#, fuzzy
msgid "Overwrite Rest Pose"
-msgstr "Écraser"
+msgstr "Écraser la position de repos"
#: editor/plugins/skeleton_editor_plugin.cpp
msgid "Create physical bones"
@@ -7927,74 +7920,62 @@ msgid "Perspective"
msgstr "Perspective"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Top Orthogonal"
-msgstr "Orthogonale"
+msgstr "Haut Orthogonal"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Top Perspective"
-msgstr "Perspective"
+msgstr "Perspective haute"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Bottom Orthogonal"
-msgstr "Orthogonale"
+msgstr "Bas Orthogonal"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Bottom Perspective"
-msgstr "Perspective"
+msgstr "Perspective basse"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Orthogonal"
-msgstr "Orthogonale"
+msgstr "Gauche Orthogonal"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspective"
+msgstr "Perspective Gauche"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Right Orthogonal"
-msgstr "Orthogonale"
+msgstr "Orthogonal Droit"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Right Perspective"
-msgstr "Perspective"
+msgstr "Perspective Droite"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Front Orthogonal"
-msgstr "Orthogonale"
+msgstr "Orthogonal avant"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Front Perspective"
-msgstr "Perspective"
+msgstr "Perspective Avant"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Rear Orthogonal"
-msgstr "Orthogonale"
+msgstr "Orthogonale arrière"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Rear Perspective"
-msgstr "Perspective"
+msgstr "Perspective arrière"
#. TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled.
#: editor/plugins/spatial_editor_plugin.cpp
msgid " [auto]"
-msgstr ""
+msgstr " [auto]"
#. TRANSLATORS: This will be appended to the view name when Portal Occulusion is enabled.
#: editor/plugins/spatial_editor_plugin.cpp
msgid " [portals active]"
-msgstr ""
+msgstr " [portails actifs]"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Transform Aborted."
@@ -8322,24 +8303,23 @@ msgstr "Vue de droite"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Vue de l'orbite vers le bas"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Vue de l'orbite vers la gauche"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Vue de l'orbite vers la droite"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Vue de devant"
+msgstr "Vue de l'orbite vers le devant"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Vue de l'orbite à 180°"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -8415,9 +8395,8 @@ msgid "View Portal Culling"
msgstr "Afficher le Portal culling"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "View Occlusion Culling"
-msgstr "Afficher le Portal culling"
+msgstr "Voir la suppression de l'occlusion"
#: editor/plugins/spatial_editor_plugin.cpp
#: modules/gridmap/grid_map_editor_plugin.cpp
@@ -8485,9 +8464,8 @@ msgid "Post"
msgstr "Post"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Unnamed Gizmo"
-msgstr "Projet sans titre"
+msgstr "Gizmo sans nom"
#: editor/plugins/sprite_editor_plugin.cpp
msgid "Create Mesh2D"
@@ -12648,14 +12626,12 @@ msgid "Set Portal Point Position"
msgstr "Définir la position du point du Portal"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Radius"
-msgstr "Changer le rayon de la forme du cylindre"
+msgstr "Définir le rayon de la sphère de l'occulteur"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Position"
-msgstr "Définir position d'entrée de la courbe"
+msgstr "Définir la position de la sphère de l'occulteur"
#: modules/csg/csg_gizmos.cpp
msgid "Change Cylinder Radius"
@@ -12943,9 +12919,8 @@ msgid "Class name can't be a reserved keyword"
msgstr "Le nom de classe ne peut pas être un mot-clé réservé"
#: modules/mono/csharp_script.cpp
-#, fuzzy
msgid "Build Solution"
-msgstr "Remplir la sélection"
+msgstr "Compiler la solution"
#: modules/mono/mono_gd/gd_mono_utils.cpp
msgid "End of inner exception stack trace"
@@ -14325,11 +14300,11 @@ msgstr ""
#: scene/3d/occluder.cpp
msgid "No shape is set."
-msgstr ""
+msgstr "Aucune forme n'est définie."
#: scene/3d/occluder.cpp
msgid "Only uniform scales are supported."
-msgstr ""
+msgstr "Seules les échelles uniformes sont prises en charge."
#: scene/3d/particles.cpp
msgid ""
@@ -14693,6 +14668,10 @@ msgid ""
"The GLES2 backend is currently in use, so these modes will act like Stretch "
"instead."
msgstr ""
+"Les options Tile et Tile Fit pour les propriétés d'extension d'axe ne sont "
+"efficaces que si vous utilisez le rendu GLES3.\n"
+"Le rendu GLES2 étant actuellement utilisé, ces modes se comporteront comme "
+"un étirement."
#: scene/gui/popup.cpp
msgid ""
@@ -14739,6 +14718,10 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Les temps d'attente très faibles des timers(< 0,05 seconde) peuvent se "
+"comporter de manière très différente selon la vitesse du rendu ou physique.\n"
+"Envisagez d'utiliser la boucle de traitement d'un script au lieu de vous "
+"fier à un timer pour les temps d'attente très faibles."
#: scene/main/viewport.cpp
msgid ""
@@ -14753,17 +14736,16 @@ msgstr ""
"RenderTarget et assignez sa texture à un nœud pouvant l'afficher."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
-"La taille de la fenêtre d'affichage doit être supérieure à 0 pour pouvoir "
-"afficher quoi que ce soit."
+"La taille de la fenêtre d'affichage doit être supérieure ou égale à 2 pixels "
+"dans les deux sens pour que le rendu soit possible."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
-msgstr ""
+msgstr "Définir les sphères pour OccluderShapeSphere"
#: scene/resources/visual_shader_nodes.cpp
msgid ""
diff --git a/editor/translations/he.po b/editor/translations/he.po
index 830033a726..9e41b7f9c4 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -966,7 +966,7 @@ msgstr "מעבר למתודה"
#: editor/create_dialog.cpp
msgid "Change %s Type"
-msgstr "שנה ×ת הסוג של s%"
+msgstr "שנה ×ת הסוג של %s"
#: editor/create_dialog.cpp editor/project_settings_editor.cpp
msgid "Change"
@@ -1026,7 +1026,7 @@ msgid ""
"Scene '%s' is currently being edited.\n"
"Changes will only take effect when reloaded."
msgstr ""
-"סצנה 's%' נמצ×ת כרגע בעריכה.\n"
+"סצנה '%s' נמצ×ת כרגע בעריכה.\n"
"×©×™× ×•×™×™× ×™×›× ×¡×• לתוקף בטעינה מחדש."
#: editor/dependency_editor.cpp
@@ -1034,7 +1034,7 @@ msgid ""
"Resource '%s' is in use.\n"
"Changes will only take effect when reloaded."
msgstr ""
-"מש×ב 's%' × ×ž×¦× ×‘×©×™×ž×•×©.\n"
+"מש×ב '%s' × ×ž×¦× ×‘×©×™×ž×•×©.\n"
"×©×™× ×•×™×™× ×™×›× ×¡×• לתוקף רק בטעינה מחדש."
#: editor/dependency_editor.cpp
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 1eb457926d..4a2075e20b 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -40,7 +40,7 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-10-15 04:33+0000\n"
+"PO-Revision-Date: 2021-10-22 06:04+0000\n"
"Last-Translator: nitenook <admin@alterbaum.net>\n"
"Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/"
"godot/ja/>\n"
@@ -2431,9 +2431,8 @@ msgstr ""
"満ãŸã›ã¾ã›ã‚“ã§ã—ãŸã€‚"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "変æ›ã—ãŸãƒ†ã‚¯ã‚¹ãƒãƒ£ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ:"
+msgstr "一ã¤ã¾ãŸã¯è¤‡æ•°ã®ã‚·ãƒ¼ãƒ³ã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸï¼"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2576,7 +2575,7 @@ msgstr "é–‰ã˜ã‚‹å‰ã«ã€'%s' ã¸ã®å¤‰æ›´ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "%s ã¯å­˜åœ¨ã—ãªããªã‚Šã¾ã—ãŸï¼æ–°ã—ã„ä¿å­˜å…ˆã‚’指定ã—ã¦ãã ã•ã„。"
#: editor/editor_node.cpp
msgid ""
@@ -3324,7 +3323,7 @@ msgstr "ライブラリã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆ"
#: editor/editor_node.cpp
msgid "Merge With Existing"
-msgstr "既存ã®(ライブラリを)マージ"
+msgstr "既存ã®ã‚‚ã®ã¨ãƒžãƒ¼ã‚¸ã™ã‚‹"
#: editor/editor_node.cpp
msgid "Apply MeshInstance Transforms"
@@ -4416,6 +4415,10 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"ã¾ã é©ç”¨ã•れã¦ã„ãªã„ä¿ç•™ä¸­ã®å¤‰æ›´ãŒã‚りã¾ã™ã€‚å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’クリックã™ã‚‹ã¨ã€ã‚¤"
+"ンãƒãƒ¼ãƒˆã®ã‚ªãƒ—ションã«åŠ ãˆãŸå¤‰æ›´ã‚’é©ç”¨ã—ã¾ã™ã€‚\n"
+"å†ã‚¤ãƒ³ãƒãƒ¼ãƒˆã‚’クリックã›ãšã«ãƒ•ァイルシステム ドックã‹ã‚‰ä»–ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’é¸æŠžã™ã‚‹"
+"ã¨ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã®ãƒ‰ãƒƒã‚¯ã§åŠ ãˆãŸå¤‰æ›´ã¯ç ´æ£„ã•れã¾ã™ã€‚"
#: editor/import_dock.cpp
msgid "Import As:"
@@ -6570,14 +6573,14 @@ msgid "Create Multiple Convex Collision Siblings"
msgstr "複数ã®å‡¸åž‹ã‚³ãƒªã‚¸ãƒ§ãƒ³ã®å…„弟を作æˆ"
#: editor/plugins/mesh_instance_editor_plugin.cpp
-#, fuzzy
msgid ""
"Creates a polygon-based collision shape.\n"
"This is a performance middle-ground between a single convex collision and a "
"polygon-based collision."
msgstr ""
"ãƒãƒªã‚´ãƒ³ãƒ™ãƒ¼ã‚¹ã®ã‚³ãƒªã‚¸ãƒ§ãƒ³ã‚·ã‚§ã‚¤ãƒ—を作æˆã—ã¾ã™ã€‚\n"
-"ã“れã¯ã€ä¸Šè¨˜ã®2ã¤ã®ã‚ªãƒ—ションã®ä¸­é–“çš„ãªãƒ‘フォーマンスã§ã™ã€‚"
+"ã“れã¯ã€å˜ä¸€ã®å‡¸åž‹ã‚³ãƒªã‚¸ãƒ§ãƒ³ã¨ãƒãƒªã‚´ãƒ³ãƒ™ãƒ¼ã‚¹ã®ã‚³ãƒªã‚¸ãƒ§ãƒ³ã®ä¸­é–“çš„ãªãƒ‘フォーマ"
+"ンスã§ã™ã€‚"
#: editor/plugins/mesh_instance_editor_plugin.cpp
msgid "Create Outline Mesh..."
@@ -6708,7 +6711,7 @@ msgstr "サーフェスを投入ã™ã‚‹"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Populate MultiMesh"
-msgstr "マルãƒãƒ¡ãƒƒã‚·ãƒ¥ã‚’投入ã™ã‚‹"
+msgstr "MultiMeshを投入ã™ã‚‹"
#: editor/plugins/multimesh_editor_plugin.cpp
msgid "Target Surface:"
@@ -7228,28 +7231,24 @@ msgid "Flip Portals"
msgstr "ãƒãƒ¼ã‚¿ãƒ«ã‚’å転"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Room Generate Points"
-msgstr "生æˆã—ãŸãƒã‚¤ãƒ³ãƒˆã®æ•°:"
+msgstr "Roomã®ãƒã‚¤ãƒ³ãƒˆã‚’生æˆ"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Generate Points"
-msgstr "生æˆã—ãŸãƒã‚¤ãƒ³ãƒˆã®æ•°:"
+msgstr "ãƒã‚¤ãƒ³ãƒˆã‚’生æˆ"
#: editor/plugins/room_manager_editor_plugin.cpp
msgid "Flip Portal"
msgstr "ãƒãƒ¼ã‚¿ãƒ«ã‚’å転"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Occluder Set Transform"
-msgstr "トランスフォームをクリア"
+msgstr "オクルーダーã®ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ォームをセット"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Center Node"
-msgstr "ノードを生æˆ"
+msgstr "中央ノード"
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "AnimationTree has no path set to an AnimationPlayer"
@@ -7386,14 +7385,12 @@ msgid "Move Down"
msgstr "下ã«ç§»å‹•"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "次ã®ã‚¹ã‚¯ãƒªãƒ—ト"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
-msgstr "ç›´å‰ã®ã‚¹ã‚¯ãƒªãƒ—ト"
+msgstr "å‰ã®ã‚¹ã‚¯ãƒªãƒ—ト"
#: editor/plugins/script_editor_plugin.cpp
msgid "File"
@@ -7810,9 +7807,8 @@ msgid "Left Orthogonal"
msgstr "å·¦å´é¢ 平行投影"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "é€è¦–投影"
+msgstr "å·¦å´é¢ é€è¦–投影"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8103,9 +8099,8 @@ msgstr ""
"ゲーム内ã®ãƒ‘フォーマンスを確実ã«ç¤ºã™ã‚‚ã®ã¨ã—ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Convert Rooms"
-msgstr "%s ã«å¤‰æ›"
+msgstr "Roomを変æ›"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "XForm Dialog"
@@ -8143,7 +8138,7 @@ msgstr "スナップを使用"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Converts rooms for portal culling."
-msgstr ""
+msgstr "ãƒãƒ¼ã‚¿ãƒ«ã‚«ãƒªãƒ³ã‚°ç”¨ã«Roomを変æ›ã—ã¾ã™ã€‚"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View"
@@ -8171,24 +8166,23 @@ msgstr "å³å´é¢å›³"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "オービットビュー 下"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "オービットビュー 左"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "オービットビュー å³"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "å‰é¢å›³"
+msgstr "オービットビュー 上"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "オービットビュー 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -8673,9 +8667,8 @@ msgid "With Data"
msgstr "データ付"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Select by data type:"
-msgstr "ãƒŽãƒ¼ãƒ‰ã‚’é¸æŠž"
+msgstr "データã®ã‚¿ã‚¤ãƒ—ã‹ã‚‰é¸æŠž:"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all visible color items."
@@ -8747,11 +8740,11 @@ msgstr ""
#: editor/plugins/theme_editor_plugin.cpp
msgid "Collapse types."
-msgstr "タイプを折りãŸãŸã‚€"
+msgstr "タイプを折りãŸãŸã‚€ã€‚"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Expand types."
-msgstr "タイプを展開"
+msgstr "タイプを展開。"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Select all Theme items."
@@ -8774,9 +8767,8 @@ msgid "Deselect all Theme items."
msgstr "ã™ã¹ã¦ã®ãƒ†ãƒ¼ãƒžã‚¢ã‚¤ãƒ†ãƒ ã®é¸æŠžã‚’解除ã™ã‚‹ã€‚"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Import Selected"
-msgstr "シーンをインãƒãƒ¼ãƒˆ"
+msgstr "é¸æŠžã•れãŸã‚‚ã®ã‚’インãƒãƒ¼ãƒˆ"
#: editor/plugins/theme_editor_plugin.cpp
msgid ""
@@ -8970,19 +8962,16 @@ msgstr ""
"ã¦ã®ã“ã®ã‚¿ã‚¤ãƒ—ã®StyleBoxã§åŒã˜ãƒ—ãƒ­ãƒ‘ãƒ†ã‚£ãŒæ›´æ–°ã•れã¾ã™ã€‚"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Type"
-msgstr "タイプ(型)"
+msgstr "タイプを追加"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Add Item Type"
-msgstr "アイテムを追加"
+msgstr "アイテムã®ã‚¿ã‚¤ãƒ—を追加"
#: editor/plugins/theme_editor_plugin.cpp
-#, fuzzy
msgid "Node Types:"
-msgstr "ノードタイプ"
+msgstr "ノードã®ã‚¿ã‚¤ãƒ—:"
#: editor/plugins/theme_editor_plugin.cpp
msgid "Show Default"
@@ -9030,6 +9019,8 @@ msgid ""
"Toggle the control picker, allowing to visually select control types for "
"edit."
msgstr ""
+"コントロールピッカーを切り替ãˆã¦ã€ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚¿ã‚¤ãƒ—を視覚的ã«é¸æŠžã—ã¦ç·¨é›†ã§"
+"ãるよã†ã«ã—ã¾ã™ã€‚"
#: editor/plugins/theme_editor_preview.cpp
msgid "Toggle Button"
@@ -9064,9 +9055,8 @@ msgid "Checked Radio Item"
msgstr "ãƒã‚§ãƒƒã‚¯æ¸ˆã¿ãƒ©ã‚¸ã‚ª アイテム"
#: editor/plugins/theme_editor_preview.cpp
-#, fuzzy
msgid "Named Separator"
-msgstr "åå‰ä»˜ã分類。"
+msgstr "åå‰ä»˜ãセパレーター"
#: editor/plugins/theme_editor_preview.cpp
msgid "Submenu"
@@ -11306,22 +11296,20 @@ msgid "Remove Translation"
msgstr "翻訳を除去"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Translation Resource Remap: Add %d Path(s)"
-msgstr "リソースå†ãƒžãƒƒãƒ—ãŒå†ãƒžãƒƒãƒ—を追加"
+msgstr "翻訳リソースã®å†ãƒžãƒƒãƒ—: %d個ã®ãƒ‘スを追加"
#: editor/project_settings_editor.cpp
-#, fuzzy
msgid "Translation Resource Remap: Add %d Remap(s)"
-msgstr "リソースå†ãƒžãƒƒãƒ—ãŒå†ãƒžãƒƒãƒ—を追加"
+msgstr "翻訳リソースã®å†ãƒžãƒƒãƒ—: %d個ã®å†ãƒžãƒƒãƒ—を追加"
#: editor/project_settings_editor.cpp
msgid "Change Resource Remap Language"
-msgstr "リソースリマップ言語を変更"
+msgstr "リソースã®å†ãƒžãƒƒãƒ—言語を変更"
#: editor/project_settings_editor.cpp
msgid "Remove Resource Remap"
-msgstr "リソースã®ãƒªãƒžãƒƒãƒ—を削除"
+msgstr "リソースã®å†ãƒžãƒƒãƒ—を削除"
#: editor/project_settings_editor.cpp
msgid "Remove Resource Remap Option"
@@ -11389,7 +11377,7 @@ msgstr "翻訳:"
#: editor/project_settings_editor.cpp
msgid "Remaps"
-msgstr "リマップ"
+msgstr "å†ãƒžãƒƒãƒ—"
#: editor/project_settings_editor.cpp
msgid "Resources:"
@@ -11397,7 +11385,7 @@ msgstr "リソース:"
#: editor/project_settings_editor.cpp
msgid "Remaps by Locale:"
-msgstr "ロケールã«å¾“ã„リマップ:"
+msgstr "ロケールã«å¾“ã„å†ãƒžãƒƒãƒ—:"
#: editor/project_settings_editor.cpp
msgid "Locale"
@@ -12456,14 +12444,12 @@ msgid "Set Portal Point Position"
msgstr "Portal ãƒã‚¤ãƒ³ãƒˆã®ä½ç½®ã‚’設定"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Radius"
-msgstr "円柱シェイプã®åŠå¾„を変更"
+msgstr "オクルーダーã®çƒå½¢ã®åŠå¾„をセット"
#: editor/spatial_editor_gizmos.cpp
-#, fuzzy
msgid "Set Occluder Sphere Position"
-msgstr "曲線ã®In-Controlã®ä½ç½®ã‚’指定"
+msgstr "オクルーダーã®çƒå½¢ã®ä½ç½®ã‚’セット"
#: modules/csg/csg_gizmos.cpp
msgid "Change Cylinder Radius"
@@ -12850,7 +12836,7 @@ msgstr ""
#: modules/visual_script/visual_script.cpp
msgid "Stack overflow with stack depth: "
-msgstr "スタックオーãƒãƒ¼ãƒ•ロー ã‚¹ã‚¿ãƒƒã‚¯ã®æ·±ã•: "
+msgstr "スタックオーãƒãƒ¼ãƒ•ロー発生 ã‚¹ã‚¿ãƒƒã‚¯ã®æ·±ã•: "
#: modules/visual_script/visual_script_editor.cpp
msgid "Change Signal Arguments"
@@ -13089,9 +13075,8 @@ msgid "Select at least one node with sequence port."
msgstr "シーケンス ãƒãƒ¼ãƒˆã‚’æŒã¤ãƒŽãƒ¼ãƒ‰ã‚’å°‘ãªãã¨ã‚‚ 1 ã¤é¸æŠžã—ã¾ã™ã€‚"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Try to only have one sequence input in selection."
-msgstr "セクションã§ã¯å”¯ä¸€ã¤ã®ã‚·ãƒ¼ã‚±ãƒ³ã‚¹å…¥åŠ›ã‚’æŒã¤ã‚ˆã†ã«ã—ã¦ãã ã•ã„。"
+msgstr "é¸æŠžã™ã‚‹ã‚·ãƒ¼ã‚±ãƒ³ã‚¹å…¥åŠ›ã¯1ã¤ã ã‘ã«ã—ã¦ãã ã•ã„。"
#: modules/visual_script/visual_script_editor.cpp
msgid "Create Function"
@@ -13187,7 +13172,7 @@ msgstr "イテレーターãŒç„¡åйã«ãªã‚Šã¾ã—ãŸ: "
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name."
-msgstr "インデックスプロパティåãŒç„¡åйã§ã™ã€‚"
+msgstr "インデックスã®ãƒ—ロパティåãŒç„¡åйã§ã™ã€‚"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Base object is not a Node!"
@@ -13473,7 +13458,7 @@ msgstr ""
msgid ""
"Unable to overwrite res://android/build/res/*.xml files with project name"
msgstr ""
-"res://android/build/res/*.xml ファイルをプロジェクトåã§ä¸Šæ›¸ãã§ãã¾ã›ã‚“。"
+"res://android/build/res/*.xml ファイルをプロジェクトåã§ä¸Šæ›¸ãã§ãã¾ã›ã‚“"
#: platform/android/export/export_plugin.cpp
msgid "Could not export project files to gradle project\n"
@@ -13855,8 +13840,8 @@ msgid ""
"A material to process the particles is not assigned, so no behavior is "
"imprinted."
msgstr ""
-"パーティクルを処ç†ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ«ã¯å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ãªã„ãŸã‚ã€å‹•作ã¯ã‚¤ãƒ³ãƒ—リン"
-"トã•れã¾ã›ã‚“。"
+"パーティクルを処ç†ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ«ãŒå‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ãªã„ãŸã‚ã€å‹•ä½œã‚’åæ˜ ã§ãã¾"
+"ã›ã‚“ã§ã—ãŸã€‚"
#: scene/2d/particles_2d.cpp
msgid ""
@@ -13966,9 +13951,8 @@ msgid "Preparing environment"
msgstr "環境を準備中"
#: scene/3d/baked_lightmap.cpp
-#, fuzzy
msgid "Generating capture"
-msgstr "ライトマップã®ç”Ÿæˆ"
+msgstr "キャプãƒãƒ£ãƒ¼ã‚’生æˆä¸­"
#: scene/3d/baked_lightmap.cpp
msgid "Saving lightmaps"
@@ -14203,6 +14187,8 @@ msgid ""
"Room convex hull contains a large number of planes.\n"
"Consider simplifying the room bound in order to increase performance."
msgstr ""
+"Roomã®å‡¸åŒ…ã«å¤§é‡ã®å¹³é¢ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚\n"
+"パフォーマンスã®å‘上ã®ãŸã‚ã«ã€Roomã®å¢ƒç•Œã®å˜ç´”化を検討ã—ã¦ãã ã•ã„。"
#: scene/3d/room_group.cpp
msgid "The RoomManager should not be placed inside a RoomGroup."
@@ -14449,6 +14435,10 @@ msgid ""
"The GLES2 backend is currently in use, so these modes will act like Stretch "
"instead."
msgstr ""
+"Axis Stretchプロパティã®TileãŠã‚ˆã³Tile Fitオプションã¯ã€GLES3レンダリングãƒãƒƒ"
+"クエンドを使用ã—ã¦ã„ã‚‹å ´åˆã«ã®ã¿æœ‰åйã§ã™ã€‚\n"
+"ç¾åœ¨GLES2ãƒãƒƒã‚¯ã‚¨ãƒ³ãƒ‰ãŒä½¿ç”¨ã•れã¦ã„ã‚‹ãŸã‚ã€ã“れらã®ãƒ¢ãƒ¼ãƒ‰ã¯ä»£ã‚りã«Stretchã®"
+"よã†ã«æŒ¯ã‚‹èˆžã„ã¾ã™ã€‚"
#: scene/gui/popup.cpp
msgid ""
@@ -14493,6 +14483,10 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"タイマーã®å¾…ã¡æ™‚é–“ãŒéžå¸¸ã«çŸ­ã„ (0.05秒未満) ã®å ´åˆã€æç”»ã¾ãŸã¯ç‰©ç†ãƒ•レーム"
+"レートã«å¿œã˜ã¦å¤§å¹…ã«å‹•作ãŒç•°ãªã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚\n"
+"éžå¸¸ã«çŸ­ã„å¾…ã¡æ™‚é–“ã®å ´åˆã€Timerを使用ã›ãšã«ã‚¹ã‚¯ãƒªãƒ—トã®processループを使用ã™"
+"ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
#: scene/main/viewport.cpp
msgid ""
@@ -14507,15 +14501,15 @@ msgstr ""
"当ã¦ã¾ã™ã€‚"
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
-msgstr "レンダーã™ã‚‹ã«ã¯ãƒ“ューãƒãƒ¼ãƒˆã®ã‚µã‚¤ã‚ºãŒ 0 より大ãã„å¿…è¦ãŒã‚りã¾ã™ã€‚"
+msgstr ""
+"レンダーã™ã‚‹ã«ã¯Viewportã®ç¸¦æ¨ªãれãžã‚ŒãŒ2ピクセル以上ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
-msgstr ""
+msgstr "OccluderShapeSphereã®çƒå½¢ã‚’セット"
#: scene/resources/visual_shader_nodes.cpp
msgid ""
@@ -14559,7 +14553,7 @@ msgstr ""
#: servers/visual/shader_language.cpp
msgid "Fragment-stage varying could not been accessed in custom function!"
-msgstr ""
+msgstr "カスタム関数内ã§Fragment-stageã®Varyingã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“ã§ã—ãŸï¼"
#: servers/visual/shader_language.cpp
msgid "Assignment to function."
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 008100444d..e78f560111 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -24,7 +24,7 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-09-29 02:21+0000\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
"Last-Translator: João Lopes <linux-man@hotmail.com>\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/godot-engine/"
"godot/pt/>\n"
@@ -2417,9 +2417,8 @@ msgstr ""
"heranças) não puderam ser satisfeitas."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Não consegui iniciar o subprocesso!"
+msgstr "Incapaz de guardar uma ou mais cenas!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2563,7 +2562,7 @@ msgstr "Guardar alterações a '%s' antes de fechar?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "% não existe mais! Especifique uma nova localização para guardar."
#: editor/editor_node.cpp
msgid ""
@@ -4410,6 +4409,10 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"Há alterações pendentes que ainda não foram aplicadas. Clique Reimportar "
+"para aplicar alterações feitas nas opções de importação.\n"
+"Se selecionar outro recurso na doca FileSystem sem Reimportar primeiro, "
+"serão rejeitadas alterações feitas na doca Import."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7376,14 +7379,12 @@ msgid "Move Down"
msgstr "Mover para baixo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Próximo Script"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
-msgstr "Script anterior"
+msgstr "Script Anterior"
#: editor/plugins/script_editor_plugin.cpp
msgid "File"
@@ -7796,9 +7797,8 @@ msgid "Left Orthogonal"
msgstr "Ortogonal Esquerda"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "Perspetiva"
+msgstr "Perspetiva Esquerda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8157,24 +8157,23 @@ msgstr "Vista Direita"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Vista Órbita Baixo"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Vista Órbita Esquerda"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Vista Órbita Direita"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Vista de Frente"
+msgstr "Vista de Órbita Cima"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Vista Órbita 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -9032,7 +9031,7 @@ msgstr "Item Desativado"
#: editor/plugins/theme_editor_preview.cpp
msgid "Check Item"
-msgstr "Verificar item"
+msgstr "Marcar item"
#: editor/plugins/theme_editor_preview.cpp
msgid "Checked Item"
@@ -11757,6 +11756,10 @@ msgid ""
"FileSystem dock context menu\n"
"or create an inherited scene using Scene > New Inherited Scene... instead."
msgstr ""
+"Incapaz de guardar o ramo do nó raiz como uma cena instanciada.\n"
+"Para criar uma cópia editável da cena atual, duplique-a usando o menu de "
+"contexto da doca FileSystem\n"
+"ou crie uma cena herdada usando Cena > Nova Cena Herdada..."
#: editor/scene_tree_dock.cpp
msgid ""
@@ -11764,6 +11767,9 @@ msgid ""
"To create a variation of a scene, you can make an inherited scene based on "
"the instanced scene using Scene > New Inherited Scene... instead."
msgstr ""
+"Incapaz de guardar o ramo de uma cena já instanciada.\n"
+"Para criar a variação de uma cena, pode fazer uma cena herdada baseada na "
+"cena instanciada usando Cena > Nova Cena Herdada..."
#: editor/scene_tree_dock.cpp
msgid "Save New Scene As..."
@@ -13281,6 +13287,8 @@ msgid ""
"Either Debug Keystore, Debug User AND Debug Password settings must be "
"configured OR none of them."
msgstr ""
+"Tanto a Keystore de Depuração, Utilizador de Depuração E Senha de Depuração "
+"têm de ser configuradas OU nenhuma delas."
#: platform/android/export/export_plugin.cpp
msgid "Debug keystore not configured in the Editor Settings nor in the preset."
@@ -13293,11 +13301,13 @@ msgid ""
"Either Release Keystore, Release User AND Release Password settings must be "
"configured OR none of them."
msgstr ""
+"Tanto a Keystore de Lançamento, Utilizador de Lançamento E Senha de "
+"Lançamento têm de ser configuradas OU nenhuma delas."
#: platform/android/export/export_plugin.cpp
msgid "Release keystore incorrectly configured in the export preset."
msgstr ""
-"Lançamento de keystore configurado incorretamente na predefinição exportada."
+"Keystore de lançamento configurado incorretamente na predefinição exportada."
#: platform/android/export/export_plugin.cpp
msgid "A valid Android SDK path is required in Editor Settings."
@@ -13371,6 +13381,10 @@ msgid ""
"directory.\n"
"The resulting %s is unsigned."
msgstr ""
+"'apksigner' não foi encontrado.\n"
+"Verifique se o comando está disponível na diretoria Android SDK build-"
+"tools.\n"
+"O % resultante não está assinado."
#: platform/android/export/export_plugin.cpp
msgid "Signing debug %s..."
@@ -13500,6 +13514,10 @@ msgid ""
"Please build a template with all required libraries, or uncheck the missing "
"architectures in the export preset."
msgstr ""
+"Bibliotecas em falta no modelo de exportação para as arquiteturas "
+"selecionadas: %s.\n"
+"Construa um modelo com todas as bibliotecas necessárias, ou desmarque as "
+"arquiteturas em falta na predefinição de exportação."
#: platform/android/export/export_plugin.cpp
msgid "Adding files..."
@@ -13584,19 +13602,19 @@ msgstr "Identificador de pacote inválido:"
#: platform/osx/export/export.cpp
msgid "Notarization: code signing required."
-msgstr ""
+msgstr "Notarização: assinatura de código necessária."
#: platform/osx/export/export.cpp
msgid "Notarization: hardened runtime required."
-msgstr ""
+msgstr "Notarização: hardened runtime necessário."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID name not specified."
-msgstr ""
+msgstr "Notarização: nome Apple ID não especificado."
#: platform/osx/export/export.cpp
msgid "Notarization: Apple ID password not specified."
-msgstr ""
+msgstr "Notarização: senha Apple ID não especificada."
#: platform/uwp/export/export.cpp
msgid "Invalid package short name."
@@ -14028,6 +14046,9 @@ msgid ""
"longer has any effect.\n"
"To remove this warning, disable the GIProbe's Compress property."
msgstr ""
+"A propriedade GIProbe Compress foi descontinuada devido a bugs conhecidos e "
+"não tem qualquer efeito.\n"
+"Para remover este aviso desative a propriedade Compress de GIProbe."
#: scene/3d/light.cpp
msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows."
@@ -14158,6 +14179,8 @@ msgid ""
"Room convex hull contains a large number of planes.\n"
"Consider simplifying the room bound in order to increase performance."
msgstr ""
+"O casco convexo do quarto contem um grande número de planos.\n"
+"Pense em simplificar os limites do quarto para melhorar o desempenho."
#: scene/3d/room_group.cpp
msgid "The RoomManager should not be placed inside a RoomGroup."
@@ -14176,6 +14199,8 @@ msgid ""
"Portal Depth Limit is set to Zero.\n"
"Only the Room that the Camera is in will render."
msgstr ""
+"Limite de Profundidade do Portal está definido como Zero.\n"
+"Só vai ser renderizado o quarto onde a Câmara está."
#: scene/3d/room_manager.cpp
msgid "There should only be one RoomManager in the SceneTree."
@@ -14186,6 +14211,8 @@ msgid ""
"RoomList path is invalid.\n"
"Please check the RoomList branch has been assigned in the RoomManager."
msgstr ""
+"Caminho do RoomList é inválido.\n"
+"Verifique se o ramo RoomList foi atribuído no RoomManager."
#: scene/3d/room_manager.cpp
msgid "RoomList contains no Rooms, aborting."
@@ -14290,7 +14317,7 @@ msgstr "Animação não encontrada: '%s'"
#: scene/animation/animation_player.cpp
msgid "Anim Apply Reset"
-msgstr ""
+msgstr "Anim Aplicar Reinicialização"
#: scene/animation/animation_tree.cpp
msgid "In node '%s', invalid animation: '%s'."
@@ -14398,6 +14425,9 @@ msgid ""
"The GLES2 backend is currently in use, so these modes will act like Stretch "
"instead."
msgstr ""
+"As opções Tile e Tile Fit para as propriedades Axis Stretch só são efetivas "
+"na renderização GLES3.\n"
+"Como GLES2 está a ser usado atualmente, estes modos funcionarão como Stretch."
#: scene/gui/popup.cpp
msgid ""
@@ -14442,6 +14472,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Tempos de espera do Timer muito baixos (< 0.05 segundos) podem originar "
+"comportamentos muito diferentes dependendo do renderizador ou da taxa de "
+"frames física.\n"
+"Considere usar um ciclo de processo de script em vez de depender de um Timer "
+"para tempos de espera muito baixos."
#: scene/main/viewport.cpp
msgid ""
@@ -14456,11 +14491,12 @@ msgstr ""
"RenderTarget e atribua a sua textura interna a outro nó para visualizar."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
-msgstr "O tamanho do viewport tem de ser maior do que 0 para renderizar."
+msgstr ""
+"O tamanho do Viewport tem de ser maior ou igual a 2 pixeis em ambas as "
+"dimensões para renderizar."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
@@ -14495,16 +14531,20 @@ msgid ""
"Varyings which assigned in 'vertex' function may not be reassigned in "
"'fragment' or 'light'."
msgstr ""
+"Variantes atribuídas na função 'vertex' não podem ser reatribuídas em "
+"'fragment' ou 'light'."
#: servers/visual/shader_language.cpp
msgid ""
"Varyings which assigned in 'fragment' function may not be reassigned in "
"'vertex' or 'light'."
msgstr ""
+"Variantes atribuídas na função 'fragment' não podem ser reatribuídas em "
+"'vertex' ou 'light'."
#: servers/visual/shader_language.cpp
msgid "Fragment-stage varying could not been accessed in custom function!"
-msgstr ""
+msgstr "Variante fragment-stage não pode ser acedida em função personalizada!"
#: servers/visual/shader_language.cpp
msgid "Assignment to function."
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 804740bf4a..9e7d53c52e 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -124,13 +124,14 @@
# William Weber Berrutti <wwberrutti@protonmail.ch>, 2021.
# Zenvasca <zenvasca@gmail.com>, 2021.
# Wladimir Roberto Barbosa <wladrbarbosa@gmail.com>, 2021.
+# Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: 2016-05-30\n"
-"PO-Revision-Date: 2021-10-09 16:52+0000\n"
-"Last-Translator: Wladimir Roberto Barbosa <wladrbarbosa@gmail.com>\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
+"Last-Translator: Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_BR/>\n"
"Language: pt_BR\n"
@@ -2521,9 +2522,8 @@ msgstr ""
"herança) não foram satisfeitas."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Não se pôde salvar textura convertida:"
+msgstr "Não foi possível salvar um ou mais cenas!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2665,7 +2665,7 @@ msgstr "Salvar alterações em '%s' antes de fechar?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "%s não existe! Por favor especifique um novo local para salvar."
#: editor/editor_node.cpp
msgid ""
@@ -2720,9 +2720,8 @@ msgid "Nothing to undo."
msgstr "Nada para desfazer."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Undo: %s"
-msgstr "Desfazer"
+msgstr "Desfazer: %s"
#: editor/editor_node.cpp
msgid "Can't redo while mouse buttons are pressed."
@@ -2733,9 +2732,8 @@ msgid "Nothing to redo."
msgstr "Nada para refazer."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Redo: %s"
-msgstr "Refazer"
+msgstr "Refazer: %s"
#: editor/editor_node.cpp
msgid "Can't reload a scene that was never saved."
@@ -3374,9 +3372,8 @@ msgid "Install from file"
msgstr "Instalar do arquivo"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Select android sources file"
-msgstr "Selecione o arquivo de fontes do Android"
+msgstr "Selecione os arquivos fontes do Android"
#: editor/editor_node.cpp
msgid ""
@@ -3463,7 +3460,6 @@ msgid "Select"
msgstr "Selecionar"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Select Current"
msgstr "Selecione Atual"
@@ -3791,9 +3787,8 @@ msgid "Uninstall these templates."
msgstr "Desinstalar esses modelos."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "There are no mirrors available."
-msgstr "Não existe o arquivo '%s'."
+msgstr "Não há espelhos disponíveis."
#: editor/export_template_manager.cpp
#, fuzzy
@@ -3809,23 +3804,20 @@ msgid "Error requesting URL:"
msgstr "Erro ao solicitar URL:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Connecting to the mirror..."
-msgstr "Conectando..."
+msgstr "Conectando ao espelho..."
#: editor/export_template_manager.cpp
msgid "Can't resolve the requested address."
msgstr "Não é possível resolver o endereço solicitado."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Can't connect to the mirror."
-msgstr "Não foi possível conectar ao host:"
+msgstr "Não foi possível conectar ao espelho."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "No response from the mirror."
-msgstr "Sem resposta do host:"
+msgstr "Sem resposta do espelho."
#: editor/export_template_manager.cpp
#: editor/plugins/asset_library_editor_plugin.cpp
@@ -3978,9 +3970,8 @@ msgstr ""
"As exportações de modelos estão instaladas e prontas para serem usadas."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Open Folder"
-msgstr "Abrir um arquivo"
+msgstr "Abrir Pasta"
#: editor/export_template_manager.cpp
msgid "Open the folder containing installed templates for the current version."
@@ -3996,14 +3987,12 @@ msgid "Uninstall templates for the current version."
msgstr "Valor inicial para o contador"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Download from:"
-msgstr "Erro ao baixar"
+msgstr "Baixar de:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Open in Web Browser"
-msgstr "Rodar no Navegador"
+msgstr "Abrir no Navegador"
#: editor/export_template_manager.cpp
#, fuzzy
@@ -4029,7 +4018,6 @@ msgstr ""
"desenvolvimento."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Install from File"
msgstr "Instalar a Partir do Arquivo"
@@ -4049,14 +4037,12 @@ msgid "Cancel the download of the templates."
msgstr "Não se pôde abrir zip dos modelos de exportação."
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Other Installed Versions:"
-msgstr "Versões Instaladas:"
+msgstr "Outras Versões Instaladas:"
#: editor/export_template_manager.cpp
-#, fuzzy
msgid "Uninstall Template"
-msgstr "Desinstalar"
+msgstr "Desinstalar Template"
#: editor/export_template_manager.cpp
msgid "Select Template File"
@@ -4576,14 +4562,12 @@ msgid "Failed to load resource."
msgstr "Falha ao carregar recurso."
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Copy Properties"
-msgstr "Propriedades"
+msgstr "Copiar Propriedades"
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Paste Properties"
-msgstr "Propriedades"
+msgstr "Colar Propriedades"
#: editor/inspector_dock.cpp
msgid "Make Sub-Resources Unique"
@@ -4639,9 +4623,8 @@ msgid "History of recently edited objects."
msgstr "Histórico dos objetos editados recentemente."
#: editor/inspector_dock.cpp
-#, fuzzy
msgid "Open documentation for this object."
-msgstr "Abrir Documentação"
+msgstr "Abrir documentação para esse objeto."
#: editor/inspector_dock.cpp editor/scene_tree_dock.cpp
msgid "Open Documentation"
@@ -4899,9 +4882,8 @@ msgid "Blend:"
msgstr "Misturar:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
-#, fuzzy
msgid "Parameter Changed:"
-msgstr "Parâmetro Modificado"
+msgstr "Parâmetro Modificado:"
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -6043,9 +6025,8 @@ msgid "Drag: Rotate selected node around pivot."
msgstr "Remover nó ou trilha selecionada."
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Alt+Drag: Move selected node."
-msgstr "Alt+Arrastar: Mover"
+msgstr "Alt+Arrastar: Mover nó selecionado."
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -6299,14 +6280,12 @@ msgid "Clear Pose"
msgstr "Limpar Pose"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Add Node Here"
-msgstr "Adicionar Nó"
+msgstr "Adicionar Nó Aqui"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Instance Scene Here"
-msgstr "Instanciar Cena(s)"
+msgstr "Instanciar Cena Aqui"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Multiply grid step by 2"
@@ -6333,34 +6312,28 @@ msgid "Zoom to 12.5%"
msgstr "Zoom para 12.5%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 25%"
-msgstr "Reduzir"
+msgstr "Zoom de 25%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 50%"
-msgstr "Reduzir"
+msgstr "Zoom de 50%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 100%"
-msgstr "Reduzir"
+msgstr "Zoom de 100%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 200%"
-msgstr "Reduzir"
+msgstr "Zoom de 200%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 400%"
-msgstr "Reduzir"
+msgstr "Zoom de 400%"
#: editor/plugins/canvas_item_editor_plugin.cpp
-#, fuzzy
msgid "Zoom to 800%"
-msgstr "Reduzir"
+msgstr "Zoom de 800%"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Zoom to 1600%"
@@ -7417,9 +7390,8 @@ msgid "Occluder Set Transform"
msgstr "Limpar Transformação"
#: editor/plugins/room_manager_editor_plugin.cpp
-#, fuzzy
msgid "Center Node"
-msgstr "Criar Nó"
+msgstr "Centralizar Nó"
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "AnimationTree has no path set to an AnimationPlayer"
@@ -7555,12 +7527,10 @@ msgid "Move Down"
msgstr "Mover para Baixo"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Próximo Script"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Script anterior"
@@ -8054,15 +8024,13 @@ msgid "None"
msgstr "Nenhum"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Rotate"
-msgstr "Status:"
+msgstr "Rotacionar"
#. TRANSLATORS: This refers to the movement that changes the position of an object.
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Translate"
-msgstr "Translação:"
+msgstr "Translação"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Scale"
@@ -8102,38 +8070,32 @@ msgid "Size:"
msgstr "Tamanho:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Objects Drawn:"
-msgstr "Objetos Desenhados"
+msgstr "Objetos Desenhados:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Material Changes:"
-msgstr "Alterações de Material"
+msgstr "Alterações de Material:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Shader Changes:"
-msgstr "Alterações de Shader"
+msgstr "Alterações de Shader:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Surface Changes:"
-msgstr "Alterações de Superfície"
+msgstr "Alterações de Superfície:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Draw Calls:"
-msgstr "Chamadas de Desenho"
+msgstr "Chamadas de Desenho:"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Vertices:"
-msgstr "Vértices"
+msgstr "Vértices:"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "FPS: %d (%s ms)"
-msgstr ""
+msgstr "FPS: %d (%s ms)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View."
@@ -13273,9 +13235,8 @@ msgid "Add Preload Node"
msgstr "Adicionar Nó de Pré-carregamento"
#: modules/visual_script/visual_script_editor.cpp
-#, fuzzy
msgid "Add Node(s)"
-msgstr "Adicionar Nó"
+msgstr "Adicionar Nó(s)"
#: modules/visual_script/visual_script_editor.cpp
msgid "Add Node(s) From Tree"
@@ -13542,17 +13503,15 @@ msgstr "Selecione um dispositivo da lista"
#: platform/android/export/export_plugin.cpp
msgid "Running on %s"
-msgstr ""
+msgstr "Executando em %s"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Exporting APK..."
-msgstr "Exportando tudo"
+msgstr "Exportando APK..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Uninstalling..."
-msgstr "Desinstalar"
+msgstr "Desinstalando..."
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -13565,14 +13524,12 @@ msgid "Could not install to device: %s"
msgstr "Não foi possível instanciar cena!"
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Running on device..."
-msgstr "Rodando Script Personalizado..."
+msgstr "Executando no dispositivo..."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Could not execute on device."
-msgstr "Não foi possível criar a pasta."
+msgstr "Não foi possível executar no dispositivo."
#: platform/android/export/export_plugin.cpp
msgid "Unable to find the 'apksigner' tool."
@@ -13707,9 +13664,8 @@ msgid "'apksigner' returned with error #%d"
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Verifying %s..."
-msgstr "Adicionando %s..."
+msgstr "Verificando %s..."
#: platform/android/export/export_plugin.cpp
msgid "'apksigner' verification of %s failed."
@@ -13797,9 +13753,8 @@ msgstr ""
"diretório do projeto gradle por saídas."
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Package not found: %s"
-msgstr "Animação não encontrada: '%s'"
+msgstr "Pacote não encontrado: '%s'"
#: platform/android/export/export_plugin.cpp
#, fuzzy
@@ -13823,9 +13778,8 @@ msgid ""
msgstr ""
#: platform/android/export/export_plugin.cpp
-#, fuzzy
msgid "Adding files..."
-msgstr "Adicionando %s..."
+msgstr "Adicionando arquivos..."
#: platform/android/export/export_plugin.cpp
#, fuzzy
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 56788509e1..df2c3c1cdf 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -98,12 +98,13 @@
# enderlorde <madel.laboratories@gmail.com>, 2021.
# Олег Довгер <oleg.a.dovger@gmail.com>, 2021.
# Anna Malinovskaia <tacitcoast@gmail.com>, 2021.
+# mrvladus <mrvladus@yandex.ru>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-09-29 02:21+0000\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
@@ -2497,9 +2498,8 @@ msgstr ""
"унаÑледованные) не могли быть удовлетворены."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Ðевозможно Ñохранить конвертированную текÑтуру:"
+msgstr "Ðе удалоÑÑŒ Ñохранить одну или неÑколько Ñцен!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2644,6 +2644,7 @@ msgstr "Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² «%s» перед закрытÐ
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
msgstr ""
+"%s больше не ÑущеÑтвует! ПожалуйÑта укажите новое меÑто Ð´Ð»Ñ ÑохранениÑ."
#: editor/editor_node.cpp
msgid ""
@@ -2785,7 +2786,7 @@ msgstr "Открыть закрытую Ñцену"
#: editor/editor_node.cpp
msgid "Unable to enable addon plugin at: '%s' parsing of config failed."
msgstr ""
-"Ðе удаётÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ плагин: «%s». Ошибка ÑинтакÑичеÑкого разбора "
+"Ðе удаётÑÑ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ плагин: «%s». Ошибка ÑинтакÑичеÑкого разбора файла "
"конфигурации."
#: editor/editor_node.cpp
@@ -4486,6 +4487,11 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"У Ð²Ð°Ñ ÐµÑть изменениÑ, которые ещё не были применены. Ðажмите "
+"«Переимпортировать», чтобы применить изменениÑ, внеÑённые в параметры "
+"импорта.\n"
+"ЕÑли выбрать другой реÑÑƒÑ€Ñ Ð² панели Â«Ð¤Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема», не нажав Ñначала "
+"«Переимпортировать», то Ñделанные в панели «Импорт» Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7453,12 +7459,10 @@ msgid "Move Down"
msgstr "ПеремеÑтить вниз"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "Следующий Ñкрипт"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Предыдущий Ñкрипт"
@@ -7877,9 +7881,8 @@ msgid "Left Orthogonal"
msgstr "Левый ортогональный"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "ПерÑпективный"
+msgstr "Левый перÑпективный"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8104,7 +8107,7 @@ msgstr "ПроÑлушиватель звука"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Enable Doppler"
-msgstr "Включить Ñффект Doppler"
+msgstr "Включить Ñффект Доплера"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Cinematic Preview"
@@ -8239,24 +8242,23 @@ msgstr "Вид Ñправа"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Вид Ñ Ð¾Ñ€Ð±Ð¸Ñ‚Ñ‹ вниз"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Вид Ñ Ð¾Ñ€Ð±Ð¸Ñ‚Ñ‹ влево"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Вид Ñ Ð¾Ñ€Ð±Ð¸Ñ‚Ñ‹ вправо"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "Вид Ñпереди"
+msgstr "Вид Ñ Ð¾Ñ€Ð±Ð¸Ñ‚Ñ‹ вверх"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Вид Ñ Ð¾Ñ€Ð±Ð¸Ñ‚Ñ‹ 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -12082,7 +12084,7 @@ msgstr "(ИÑточник)"
#: editor/scene_tree_editor.cpp
msgid "Node configuration warning:"
-msgstr "Конфигурации узла, предупреждение:"
+msgstr "Предупреждение о конфигурации узла:"
#: editor/scene_tree_editor.cpp
msgid ""
@@ -14565,6 +14567,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Очень низкое Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ñ‚Ð°Ð¹Ð¼ÐµÑ€Ð° (< 0,05 Ñекунды) может привеÑти к "
+"значительно разному поведению, в завиÑимоÑти от чаÑтоты кадров рендеринга "
+"или физики.\n"
+"РаÑÑмотрите возможноÑть иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ†Ð¸ÐºÐ»Ð° обработки в Ñкрипте вмеÑто "
+"таймера Ñ Ð¾Ñ‡ÐµÐ½ÑŒ низким временем ожиданиÑ."
#: scene/main/viewport.cpp
msgid ""
@@ -14580,11 +14587,12 @@ msgstr ""
"либо узлу Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
-msgstr "Размер окна проÑмотра должен быть больше 0 Ð´Ð»Ñ Ñ€ÐµÐ½Ð´ÐµÑ€Ð¸Ð½Ð³Ð°."
+msgstr ""
+"Размер облаÑти проÑмотра должен быть больше или равен 2 пикÑелÑм в обоих "
+"измерениÑÑ…, чтобы отобразить что-либо."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index 2ae502bdd5..f22e9500e1 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -3,7 +3,7 @@
# Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
# bergmarklund <davemcgroin@gmail.com>, 2017, 2018.
-# Christoffer Sundbom <christoffer_karlsson@live.se>, 2017.
+# Christoffer Sundbom <christoffer_karlsson@live.se>, 2017, 2021.
# Jakob Sinclair <sinclair.jakob@mailbox.org>, 2018.
# . <grenoscar@gmail.com>, 2018, 2020.
# Kristoffer Grundström <kristoffer.grundstrom1983@gmail.com>, 2018.
@@ -28,8 +28,8 @@ msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-08-10 21:40+0000\n"
-"Last-Translator: Kristoffer Grundström <swedishsailfishosuser@tutanota.com>\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
+"Last-Translator: Christoffer Sundbom <christoffer_karlsson@live.se>\n"
"Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/"
"godot/sv/>\n"
"Language: sv\n"
@@ -37,7 +37,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.8-dev\n"
+"X-Generator: Weblate 4.9-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -2146,9 +2146,8 @@ msgid "Methods"
msgstr "Metoder"
#: editor/editor_help.cpp
-#, fuzzy
msgid "Theme Properties"
-msgstr "Egenskaper"
+msgstr "Tema Egenskaper"
#: editor/editor_help.cpp
msgid "Enumerations"
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index d662cfea7b..db324bbc2c 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -22,7 +22,7 @@ msgstr ""
"Project-Id-Version: Ukrainian (Godot Engine)\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-09-22 20:30+0000\n"
+"PO-Revision-Date: 2021-10-18 15:35+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
"Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/"
"godot/uk/>\n"
@@ -2426,9 +2426,8 @@ msgstr ""
"уÑпадковані) не задоволені."
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "Ðе вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити підпроцеÑ!"
+msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ одну або декілька Ñцен!"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2571,7 +2570,7 @@ msgstr "Зберегти зміни, внеÑені до '%s' перед закÑ
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "%s вже не Ñ–Ñнує! Будь лаÑка, вкажіть нове міÑце Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ."
#: editor/editor_node.cpp
msgid ""
@@ -4421,6 +4420,11 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"ВнеÑені вами зміни ще не заÑтоÑовано. ÐатиÑніть кнопку «Імпортувати "
+"повторно», щоб заÑтоÑувати зміни у параметрах імпортуваннÑ.\n"
+"Вибір іншого реÑурÑу на бічній панелі файлової ÑиÑтеми без натиÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "
+"«Імпортувати повторно» призведе до Ð²Ñ–Ð´ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ð½, Ñкі було внеÑено на "
+"бічній панелі імпортуваннÑ."
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7400,12 +7404,10 @@ msgid "Move Down"
msgstr "ПереміÑтити вниз"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "ÐаÑтупний Ñкрипт"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "Попередній Ñкрипт"
@@ -7824,9 +7826,8 @@ msgid "Left Orthogonal"
msgstr "Лівий ортогональний"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "ПерÑпектива"
+msgstr "Ліва перÑпектива"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8185,24 +8186,23 @@ msgstr "ВиглÑд Ñправа"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "Орбітальний вид вниз"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "Орбітальний вид ліворуч"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "Орбітальний вид праворуч"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "ВиглÑд Ñпереду"
+msgstr "Орбітальний вид згори"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "Орбітальний вид 180"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -14554,6 +14554,11 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"Дуже малі проміжки чаÑу Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° таймером (< 0.05 Ñекунд) можуть "
+"призводити до Ñуттєво різних результатів Ð´Ð»Ñ Ñ€Ñ–Ð·Ð½Ð¸Ñ… оброблених або фізичних "
+"чаÑтот кадрів.\n"
+"Вам варто ÑкориÑтатиÑÑ Ñ†Ð¸ÐºÐ»Ð¾Ð¼ процеÑу Ñкрипту заміÑть Timer Ð´Ð»Ñ Ð´ÑƒÐ¶Ðµ малих "
+"проміжків очікуваннÑ."
#: scene/main/viewport.cpp
msgid ""
@@ -14568,13 +14573,12 @@ msgstr ""
"пов'Ñзати Ñ—Ñ— внутрішню текÑтуру з одним із вузлів Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ."
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
msgstr ""
"Щоб програма могла хоч щоÑÑŒ показати, розмір Ð¿Ð¾Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду має бути більшим "
-"за 0."
+"або рівним 2 пікÑелÑм в обох вимірах."
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index f17a8af827..82159d534e 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -79,12 +79,15 @@
# suplife <2634557184@qq.com>, 2021.
# luoji <564144019@qq.com>, 2021.
# zeng haochen <m18621006730@163.com>, 2021.
+# Sam Sun <oppositenormal@outlook.com>, 2021.
+# è‹è½¼ <youwanyuyu@gmail.com>, 2021.
+# nitenook <admin@alterbaum.net>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"Report-Msgid-Bugs-To: https://github.com/godotengine/godot\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2021-10-08 03:03+0000\n"
+"PO-Revision-Date: 2021-10-21 10:31+0000\n"
"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hans/>\n"
@@ -2435,9 +2438,8 @@ msgid ""
msgstr "无法ä¿å­˜åœºæ™¯ã€‚å¯èƒ½æ˜¯å› ä¸ºä¾èµ–项(实例或继承)无法满足。"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Could not save one or more scenes!"
-msgstr "无法ä¿å­˜è½¬æ¢çš„贴图:"
+msgstr "无法ä¿å­˜ä¸€ä¸ªæˆ–多个场景ï¼"
#: editor/editor_node.cpp
msgid "Save All Scenes"
@@ -2573,7 +2575,7 @@ msgstr "是å¦åœ¨å…³é—­å‰ä¿å­˜å¯¹ “%s†的更改?"
#: editor/editor_node.cpp
msgid "%s no longer exists! Please specify a new save location."
-msgstr ""
+msgstr "路径 %s å·²ä¸å­˜åœ¨ï¼è¯·é‡æ–°é€‰æ‹©æ–°çš„ä¿å­˜è·¯å¾„。"
#: editor/editor_node.cpp
msgid ""
@@ -4362,6 +4364,8 @@ msgid ""
"Selecting another resource in the FileSystem dock without clicking Reimport "
"first will discard changes made in the Import dock."
msgstr ""
+"æœ‰äº›ä¿®æ”¹æœªè¢«åº”ç”¨ã€‚ç‚¹å‡»â€œé‡æ–°å¯¼å…¥â€æ¥åº”用导入的修改。\n"
+"若在选择å¦ä¸€ä¸ªèµ„æºå‰æ²¡æœ‰ç‚¹å‡»â€œé‡æ–°å¯¼å…¥â€ï¼Œåˆ™ä¼šå¿½ç•¥å¯¼å…¥çš„修改。"
#: editor/import_dock.cpp
msgid "Import As:"
@@ -7289,12 +7293,10 @@ msgid "Move Down"
msgstr "å‘下移动"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Next Script"
msgstr "下一个脚本"
#: editor/plugins/script_editor_plugin.cpp
-#, fuzzy
msgid "Previous Script"
msgstr "上一个脚本"
@@ -7709,9 +7711,8 @@ msgid "Left Orthogonal"
msgstr "正交左视图"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Left Perspective"
-msgstr "é€è§†"
+msgstr "é€è§†å·¦è§†å›¾"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Right Orthogonal"
@@ -8067,24 +8068,23 @@ msgstr "å³è§†å›¾"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Down"
-msgstr ""
+msgstr "视图å‘下环绕"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Left"
-msgstr ""
+msgstr "视图å‘左环绕"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View Right"
-msgstr ""
+msgstr "视图å‘å³çŽ¯ç»•"
#: editor/plugins/spatial_editor_plugin.cpp
-#, fuzzy
msgid "Orbit View Up"
-msgstr "å‰è§†å›¾"
+msgstr "视图å‘上环绕"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Orbit View 180"
-msgstr ""
+msgstr "视图环绕至背é¢"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Switch Perspective/Orthogonal View"
@@ -14195,6 +14195,9 @@ msgid ""
"Consider using a script's process loop instead of relying on a Timer for "
"very low wait times."
msgstr ""
+"计时器等待时间éžå¸¸çŸ­ï¼ˆå°äºŽ 0.05 秒)时å¯èƒ½ä¼šæ ¹æ®æ¸²æŸ“帧率和物ç†å¸§çŽ‡çš„ä¸åŒè€Œè¡¨"
+"现得æžä¸ºä¸åŒã€‚\n"
+"建议使用脚本的 process 循环代替此类计时器。"
#: scene/main/viewport.cpp
msgid ""
@@ -14203,16 +14206,15 @@ msgid ""
"obtain a size. Otherwise, make it a RenderTarget and assign its internal "
"texture to some node for display."
msgstr ""
-"这个 Viewport 未被设置为渲染目标。如果你想让其直接在å±å¹•上显示内容,请使其æˆ"
-"为 Control çš„å­èŠ‚ç‚¹ï¼Œè¿™æ ·ä¸€æ¥è¯¥ Viewport æ‰ä¼šæœ‰å¤§å°ã€‚å¦åˆ™è¯·ä¸ºå…¶è®¾ç½® "
+"这个视窗未被设置为渲染目标。如果你想让其直接在å±å¹•上显示内容,请使其æˆä¸º "
+"Control çš„å­èŠ‚ç‚¹ï¼Œè¿™æ ·ä¸€æ¥è¯¥ Viewport æ‰ä¼šæœ‰å¤§å°ã€‚å¦åˆ™è¯·ä¸ºå…¶è®¾ç½® "
"RenderTarget 并分é…å…¶å†…éƒ¨çº¹ç†æ¥æ˜¾ç¤ºã€‚"
#: scene/main/viewport.cpp
-#, fuzzy
msgid ""
"The Viewport size must be greater than or equal to 2 pixels on both "
"dimensions to render anything."
-msgstr "Viewport 大å°å¤§äºŽ 0 æ—¶æ‰èƒ½è¿›è¡Œæ¸²æŸ“。"
+msgstr "Viewport 的宽高都大于等于 2 åƒç´ æ—¶æ‰èƒ½è¿›è¡Œæ¸²æŸ“。"
#: scene/resources/occluder_shape.cpp
msgid "OccluderShapeSphere Set Spheres"
diff --git a/methods.py b/methods.py
index 77a1085baf..b2eb7b7c77 100644
--- a/methods.py
+++ b/methods.py
@@ -1,9 +1,9 @@
-import collections
import os
import re
import glob
import subprocess
from collections import OrderedDict
+from collections.abc import Mapping
from typing import Iterator
# We need to define our own `Action` method to control the verbosity of output
@@ -662,7 +662,7 @@ def generate_vs_project(env, num_jobs):
batch_file = find_visual_c_batch_file(env)
if batch_file:
- class ModuleConfigs(collections.Mapping):
+ class ModuleConfigs(Mapping):
# This version information (Win32, x64, Debug, Release, Release_Debug seems to be
# required for Visual Studio to understand that it needs to generate an NMAKE
# project. Do not modify without knowing what you are doing.
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 3112f1af5f..de5d9c3f06 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -76,7 +76,7 @@ fi
# To get consistent formatting, we recommend contributors to use the same
# clang-format version as CI.
-RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="11"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="12"
RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="13"
if [ ! -x "$CLANG_FORMAT" ] ; then
@@ -146,7 +146,7 @@ do
# +++ - timestamp
# to both lines working on the same file and having a/ and b/ prefix.
# Else it can not be applied with 'git apply'.
- "$CLANG_FORMAT" -style=file "$file" | \
+ "$CLANG_FORMAT" -style=file "$file" --Wno-error=unknown | \
diff -u "$file" - | \
sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
done
diff --git a/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh
index bcd63aa73b..b0020da597 100755
--- a/misc/scripts/clang_format.sh
+++ b/misc/scripts/clang_format.sh
@@ -23,7 +23,7 @@ while IFS= read -rd '' f; do
for extension in ${CLANG_FORMAT_FILE_EXTS[@]}; do
if [[ "$f" == *"$extension" ]]; then
# Run clang-format.
- clang-format -i "$f"
+ clang-format --Wno-error=unknown -i "$f"
# Fix copyright headers, but not all files get them.
if [[ "$f" == *"inc" ]]; then
continue 2
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index b8da3a713b..0df08a7996 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -6460,7 +6460,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
for (int32_t shape_i = 0; shape_i < mesh->get_blend_shape_count(); shape_i++) {
String shape_name = mesh->get_blend_shape_name(shape_i);
NodePath shape_path = String(path) + ":" + shape_name;
- int32_t shape_track_i = animation->find_track(shape_path);
+ int32_t shape_track_i = animation->find_track(shape_path, Animation::TYPE_BLEND_SHAPE);
if (shape_track_i == -1) {
GLTFAnimation::Channel<float> weight;
weight.interpolation = GLTFAnimation::INTERP_LINEAR;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 26a04a358d..531f600c3f 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1813,8 +1813,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
}
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
- p_properties->push_back(E.value);
+ for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = script->member_info.front(); E; E = E.next()) {
+ p_properties->push_front(E.value());
}
// Call _get_property_list
@@ -1839,10 +1839,9 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
for (int i = 0, size = array.size(); i < size; i++) {
p_properties->push_back(PropertyInfo::from_dict(array.get(i)));
}
- return;
}
- break;
+ return;
}
top = top->get_parent_class();
@@ -1865,8 +1864,9 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *
}
void CSharpInstance::get_method_list(List<MethodInfo> *p_list) const {
- if (!script->is_valid() || !script->script_class)
+ if (!script->is_valid() || !script->script_class) {
return;
+ }
GD_MONO_SCOPE_THREAD_ATTACH;
@@ -3499,9 +3499,9 @@ Ref<Script> CSharpScript::get_base_script() const {
return Ref<Script>();
}
-void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const {
- for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
- p_list->push_back(E.value);
+void CSharpScript::get_script_property_list(List<PropertyInfo> *r_list) const {
+ for (OrderedHashMap<StringName, PropertyInfo>::ConstElement E = member_info.front(); E; E = E.next()) {
+ r_list->push_front(E.value());
}
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index afc17f694a..c998d9c1e4 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -154,7 +154,7 @@ private:
Set<StringName> exported_members_names;
#endif
- Map<StringName, PropertyInfo> member_info;
+ OrderedHashMap<StringName, PropertyInfo> member_info;
void _clear();
@@ -215,7 +215,7 @@ public:
void get_script_signal_list(List<MethodInfo> *r_signals) const override;
bool get_property_default_value(const StringName &p_property, Variant &r_value) const override;
- void get_script_property_list(List<PropertyInfo> *p_list) const override;
+ void get_script_property_list(List<PropertyInfo> *r_list) const override;
void update_exports() override;
void get_members(Set<StringName> *p_members) override;
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index e95369ead7..c459141265 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1211,6 +1211,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
}
_FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const {
+ ERR_FAIL_COND_V(p_size.x <= 0, false);
if (p_font_data->cache.has(p_size)) {
return true;
}
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 193588c4ed..f598eb80ea 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -670,6 +670,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
}
_FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const {
+ ERR_FAIL_COND_V(p_size.x <= 0, false);
if (p_font_data->cache.has(p_size)) {
return true;
}
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 87bb2ea218..efdcc6c77b 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -158,9 +158,9 @@ def templateBuildTasks() {
/**
* Master task used to coordinate the tasks defined above to generate the set of Godot templates.
*/
-task generateGodotTemplates(type: GradleBuild) {
- startParameter.excludedTaskNames = templateExcludedBuildTask()
- tasks = templateBuildTasks()
+task generateGodotTemplates {
+ gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
+ dependsOn = templateBuildTasks()
finalizedBy 'zipCustomBuild'
}
@@ -168,12 +168,12 @@ task generateGodotTemplates(type: GradleBuild) {
/**
* Generates the same output as generateGodotTemplates but with dev symbols
*/
-task generateDevTemplate (type: GradleBuild) {
+task generateDevTemplate {
// add parameter to set symbols to true
- startParameter.projectProperties += [doNotStrip: true]
+ gradle.startParameter.projectProperties += [doNotStrip: true]
- startParameter.excludedTaskNames = templateExcludedBuildTask()
- tasks = templateBuildTasks()
+ gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
+ dependsOn = templateBuildTasks()
finalizedBy 'zipCustomBuild'
}
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index c0e5aac938..212b6762e1 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -124,6 +124,7 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
#ifdef DBUS_ENABLED
case FEATURE_KEEP_SCREEN_ON:
#endif
+ case FEATURE_CLIPBOARD_PRIMARY:
return true;
default: {
}
diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp
index 271a4da705..00bfa62449 100644
--- a/scene/2d/collision_polygon_2d.cpp
+++ b/scene/2d/collision_polygon_2d.cpp
@@ -131,6 +131,7 @@ void CollisionPolygon2D::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
+ ERR_FAIL_COND(!is_inside_tree());
if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
break;
}
diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp
index 54cb851216..c7742c7ba5 100644
--- a/scene/2d/collision_shape_2d.cpp
+++ b/scene/2d/collision_shape_2d.cpp
@@ -88,6 +88,8 @@ void CollisionShape2D::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
+ ERR_FAIL_COND(!is_inside_tree());
+
if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
break;
}
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index 3ac2128c2e..0a8e9e2a58 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -157,6 +157,7 @@ void RayCast2D::_notification(int p_what) {
} break;
case NOTIFICATION_DRAW: {
+ ERR_FAIL_COND(!is_inside_tree());
if (!Engine::get_singleton()->is_editor_hint() && !get_tree()->is_debugging_collisions_hint()) {
break;
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 48ef41e015..55feb02fce 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -73,6 +73,7 @@ void CPUParticles3D::set_amount(int p_amount) {
}
particle_data.resize((12 + 4 + 4) * p_amount);
+ RS::get_singleton()->multimesh_set_visible_instances(multimesh, -1);
RS::get_singleton()->multimesh_allocate_data(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true);
particle_order.resize(p_amount);
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index fbc3767151..e3744ad5e9 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -178,32 +178,32 @@ void Skeleton3D::_get_property_list(List<PropertyInfo> *p_list) const {
}
void Skeleton3D::_validate_property(PropertyInfo &property) const {
- PackedStringArray spr = property.name.split("/");
- if (spr.size() == 3 && spr[0] == "bones") {
- if (spr[2] == "rest") {
+ PackedStringArray split = property.name.split("/");
+ if (split.size() == 3 && split[0] == "bones") {
+ if (split[2] == "rest") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
if (is_show_rest_only()) {
- if (spr[2] == "enabled") {
+ if (split[2] == "enabled") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- if (spr[2] == "position") {
+ if (split[2] == "position") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- if (spr[2] == "rotation") {
+ if (split[2] == "rotation") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- if (spr[2] == "scale") {
+ if (split[2] == "scale") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- } else if (!is_bone_enabled(spr[1].to_int())) {
- if (spr[2] == "position") {
+ } else if (!is_bone_enabled(split[1].to_int())) {
+ if (split[2] == "position") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- if (spr[2] == "rotation") {
+ if (split[2] == "rotation") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
- if (spr[2] == "scale") {
+ if (split[2] == "scale") {
property.usage |= PROPERTY_USAGE_READ_ONLY;
}
}
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index c1db684d9b..046d256867 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -129,7 +129,7 @@ void CodeEdit::_notification(int p_what) {
}
const int scroll_width = code_completion_options_count > code_completion_max_lines ? code_completion_scroll_width : 0;
- const int code_completion_base_width = font->get_string_size(code_completion_base).width;
+ const int code_completion_base_width = font->get_string_size(code_completion_base, font_size).width;
if (caret_pos.x - code_completion_base_width + code_completion_rect.size.width + scroll_width > get_size().width) {
code_completion_rect.position.x = get_size().width - code_completion_rect.size.width - scroll_width;
} else {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 973074397b..77a1efd021 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -400,7 +400,7 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_NONE, "", usage));
+ p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater", usage));
}
}
{
@@ -637,7 +637,9 @@ void Control::_notification(int p_notification) {
}
} else {
//is a regular root control or top_level
- data.RI = get_viewport()->_gui_add_root_control(this);
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ data.RI = viewport->_gui_add_root_control(this);
}
data.parent_canvas_item = get_parent_item();
@@ -646,7 +648,9 @@ void Control::_notification(int p_notification) {
data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
} else {
//connect viewport
- get_viewport()->connect("size_changed", callable_mp(this, &Control::_size_changed));
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ viewport->connect("size_changed", callable_mp(this, &Control::_size_changed));
}
} break;
case NOTIFICATION_EXIT_CANVAS: {
@@ -655,7 +659,9 @@ void Control::_notification(int p_notification) {
data.parent_canvas_item = nullptr;
} else if (!is_set_as_top_level()) {
//disconnect viewport
- get_viewport()->disconnect("size_changed", callable_mp(this, &Control::_size_changed));
+ Viewport *viewport = get_viewport();
+ ERR_FAIL_COND(!viewport);
+ viewport->disconnect("size_changed", callable_mp(this, &Control::_size_changed));
}
if (data.RI) {
@@ -979,7 +985,7 @@ Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const String
Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const Ref<Font> *font = data.font_override.getptr(p_name);
- if (font) {
+ if (font && (*font)->get_data_count() > 0) {
return *font;
}
}
@@ -992,7 +998,7 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_
int Control::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
const int *font_size = data.font_size_override.getptr(p_name);
- if (font_size) {
+ if (font_size && (*font_size) > 0) {
return *font_size;
}
}
@@ -2580,16 +2586,6 @@ void Control::warp_mouse(const Point2 &p_to_pos) {
}
bool Control::is_text_field() const {
- /*
- if (get_script_instance()) {
- Variant v=p_point;
- const Variant *p[2]={&v,&p_data};
- Callable::CallError ce;
- Variant ret = get_script_instance()->call("is_text_field",p,2,ce);
- if (ce.error==Callable::CallError::CALL_OK)
- return ret;
- }
- */
return false;
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 99c5e3bf0c..dda1151273 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -235,7 +235,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
return;
}
- if (is_middle_mouse_paste_enabled() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_MIDDLE && is_editable()) {
+ if (is_middle_mouse_paste_enabled() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_MIDDLE && is_editable() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary().strip_escapes();
deselect();
@@ -290,7 +290,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
selection.double_click = true;
last_dblclk = 0;
caret_column = selection.begin;
- if (!pass) {
+ if (!pass && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(text);
}
} else if (b->is_double_click()) {
@@ -308,7 +308,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
break;
}
}
- if (!pass) {
+ if (!pass && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(text.substr(selection.begin, selection.end - selection.begin));
}
}
@@ -328,7 +328,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
update();
} else {
- if (selection.enabled && !pass && b->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (selection.enabled && !pass && b->get_button_index() == MOUSE_BUTTON_LEFT && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(text.substr(selection.begin, selection.end - selection.begin));
}
if (!text.is_empty() && is_editable() && clear_button_enabled) {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index b3788f6317..31767dd263 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1596,14 +1596,16 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
selection.to_char = words[i + 1];
selection.active = true;
- DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
update();
break;
}
}
}
} else if (!b->is_pressed()) {
- if (selection.enabled) {
+ if (selection.enabled && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
}
selection.click_item = nullptr;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index a1d66d8544..8cb3b23020 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1534,7 +1534,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
update();
}
- if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) {
+ if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
paste_primary_clipboard();
}
@@ -1575,7 +1575,9 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
dragging_selection = false;
can_drag_minimap = false;
click_select_held->stop();
- DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
}
// Notify to show soft keyboard.
@@ -5167,7 +5169,7 @@ void TextEdit::_paste_internal() {
}
void TextEdit::_paste_primary_clipboard_internal() {
- if (!is_editable()) {
+ if (!is_editable() || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
return;
}
@@ -5520,7 +5522,9 @@ void TextEdit::_update_selection_mode_word() {
}
}
- DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
update();
@@ -5549,7 +5553,9 @@ void TextEdit::_update_selection_mode_line() {
set_caret_column(0);
select(selection.selecting_line, selection.selecting_column, line, col);
- DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
update();
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 3f041bf65a..1245a37c4d 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3570,7 +3570,9 @@ int Tree::_get_title_button_height() const {
void Tree::_notification(int p_what) {
if (p_what == NOTIFICATION_FOCUS_ENTER) {
- focus_in_id = get_viewport()->get_processed_events_count();
+ if (get_viewport()) {
+ focus_in_id = get_viewport()->get_processed_events_count();
+ }
}
if (p_what == NOTIFICATION_MOUSE_EXIT) {
if (cache.hover_type != Cache::CLICK_NONE) {
@@ -4035,7 +4037,7 @@ int Tree::get_column_minimum_width(int p_column) const {
// Check if the visible title of the column is wider.
if (show_column_titles) {
- min_width = MAX(cache.font->get_string_size(columns[p_column].title).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
+ min_width = MAX(cache.font->get_string_size(columns[p_column].title, cache.font_size).width + cache.bg->get_margin(SIDE_LEFT) + cache.bg->get_margin(SIDE_RIGHT), min_width);
}
if (!columns[p_column].clip_content) {
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 916833c9a7..5065684839 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -892,9 +892,9 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
- ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "align", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "align", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_multiline_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "next", "size", "modulate", "outline_size", "outline_modulate"), &CanvasItem::draw_char, DEFVAL(""), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)));
+ ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "align", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "font", "pos", "text", "align", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &CanvasItem::draw_multiline_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "next", "size", "modulate", "outline_size", "outline_modulate"), &CanvasItem::draw_char, DEFVAL(""), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)));
ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "transform", "modulate"), &CanvasItem::draw_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture"), &CanvasItem::draw_multimesh);
ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0)));
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index ba9f47119d..04376ad809 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -34,10 +34,10 @@
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "scene/resources/canvas_item_material.h"
+#include "scene/resources/font.h"
#include "servers/text_server.h"
class CanvasLayer;
-class Font;
class MultiMesh;
class StyleBox;
class Window;
@@ -235,9 +235,9 @@ public:
void draw_mesh(const Ref<Mesh> &p_mesh, const Ref<Texture2D> &p_texture, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1));
void draw_multimesh(const Ref<MultiMesh> &p_multimesh, const Ref<Texture2D> &p_texture);
- void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- real_t draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
+ void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ void draw_multiline_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ real_t draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", int p_size = Font::DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0));
void draw_set_transform_matrix(const Transform2D &p_matrix);
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 08b78a39b1..f8e4845ae6 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -30,13 +30,40 @@
#include "animation.h"
+#include "core/io/marshalls.h"
#include "core/math/geometry_3d.h"
#include "scene/scene_string_names.h"
bool Animation::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
- if (name.begins_with("tracks/")) {
+ if (p_name == SNAME("_compression")) {
+ ERR_FAIL_COND_V(tracks.size() > 0, false); //can only set compression if no tracks exist
+ Dictionary comp = p_value;
+ ERR_FAIL_COND_V(!comp.has("fps"), false);
+ ERR_FAIL_COND_V(!comp.has("bounds"), false);
+ ERR_FAIL_COND_V(!comp.has("pages"), false);
+ ERR_FAIL_COND_V(!comp.has("format_version"), false);
+ uint32_t format_version = comp["format_version"];
+ ERR_FAIL_COND_V(format_version > Compression::FORMAT_VERSION, false); // version does not match this supported version
+ compression.fps = comp["fps"];
+ Array bounds = comp["bounds"];
+ compression.bounds.resize(bounds.size());
+ for (int i = 0; i < bounds.size(); i++) {
+ compression.bounds[i] = bounds[i];
+ }
+ Array pages = comp["pages"];
+ compression.pages.resize(pages.size());
+ for (int i = 0; i < pages.size(); i++) {
+ Dictionary page = pages[i];
+ ERR_FAIL_COND_V(!page.has("data"), false);
+ ERR_FAIL_COND_V(!page.has("time_offset"), false);
+ compression.pages[i].data = page["data"];
+ compression.pages[i].time_offset = page["time_offset"];
+ }
+ compression.enabled = true;
+ return true;
+ } else if (name.begins_with("tracks/")) {
int track = name.get_slicec('/', 1).to_int();
String what = name.get_slicec('/', 2);
@@ -72,6 +99,34 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
if (what == "path") {
track_set_path(track, p_value);
+ } else if (what == "compressed_track") {
+ int index = p_value;
+ ERR_FAIL_COND_V(!compression.enabled, false);
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)index, compression.bounds.size(), false);
+ Track *t = tracks[track];
+ t->interpolation = INTERPOLATION_LINEAR; //only linear supported
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ PositionTrack *tt = static_cast<PositionTrack *>(t);
+ tt->compressed_track = index;
+ } break;
+ case TYPE_ROTATION_3D: {
+ RotationTrack *rt = static_cast<RotationTrack *>(t);
+ rt->compressed_track = index;
+ } break;
+ case TYPE_SCALE_3D: {
+ ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ st->compressed_track = index;
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ bst->compressed_track = index;
+ } break;
+ default: {
+ return false;
+ }
+ }
+ return true;
} else if (what == "interp") {
track_set_interpolation_type(track, InterpolationType(p_value.operator int()));
} else if (what == "loop_wrap") {
@@ -369,7 +424,30 @@ bool Animation::_set(const StringName &p_name, const Variant &p_value) {
bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
String name = p_name;
- if (name == "length") {
+ if (p_name == SNAME("_compression")) {
+ ERR_FAIL_COND_V(!compression.enabled, false);
+ Dictionary comp;
+ comp["fps"] = compression.fps;
+ Array bounds;
+ bounds.resize(compression.bounds.size());
+ for (uint32_t i = 0; i < compression.bounds.size(); i++) {
+ bounds[i] = compression.bounds[i];
+ }
+ comp["bounds"] = bounds;
+ Array pages;
+ pages.resize(compression.pages.size());
+ for (uint32_t i = 0; i < compression.pages.size(); i++) {
+ Dictionary page;
+ page["data"] = compression.pages[i].data;
+ page["time_offset"] = compression.pages[i].time_offset;
+ pages[i] = page;
+ }
+ comp["pages"] = pages;
+ comp["format_version"] = Compression::FORMAT_VERSION;
+
+ r_ret = comp;
+ return true;
+ } else if (name == "length") {
r_ret = length;
} else if (name == "loop") {
r_ret = loop;
@@ -414,6 +492,34 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
} else if (what == "path") {
r_ret = track_get_path(track);
+ } else if (what == "compressed_track") {
+ ERR_FAIL_COND_V(!compression.enabled, false);
+ Track *t = tracks[track];
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ PositionTrack *tt = static_cast<PositionTrack *>(t);
+ r_ret = tt->compressed_track;
+ } break;
+ case TYPE_ROTATION_3D: {
+ RotationTrack *rt = static_cast<RotationTrack *>(t);
+ r_ret = rt->compressed_track;
+ } break;
+ case TYPE_SCALE_3D: {
+ ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ r_ret = st->compressed_track;
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ r_ret = bst->compressed_track;
+ } break;
+ default: {
+ r_ret = Variant();
+ ERR_FAIL_V(false);
+ }
+ }
+
+ return true;
+
} else if (what == "interp") {
r_ret = track_get_interpolation_type(track);
} else if (what == "loop_wrap") {
@@ -692,14 +798,21 @@ bool Animation::_get(const StringName &p_name, Variant &r_ret) const {
}
void Animation::_get_property_list(List<PropertyInfo> *p_list) const {
+ if (compression.enabled) {
+ p_list->push_back(PropertyInfo(Variant::DICTIONARY, "_compression", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ }
for (int i = 0; i < tracks.size(); i++) {
p_list->push_back(PropertyInfo(Variant::STRING, "tracks/" + itos(i) + "/type", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tracks/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/imported", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/enabled", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
- p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::NODE_PATH, "tracks/" + itos(i) + "/path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ if (track_is_compressed(i)) {
+ p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/compressed_track", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ } else {
+ p_list->push_back(PropertyInfo(Variant::INT, "tracks/" + itos(i) + "/interp", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "tracks/" + itos(i) + "/loop_wrap", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, "tracks/" + itos(i) + "/keys", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
+ }
}
}
@@ -765,21 +878,25 @@ void Animation::remove_track(int p_track) {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ ERR_FAIL_COND_MSG(tt->compressed_track >= 0, "Compressed tracks can't be manually removed. Call clear() to get rid of compression first.");
_clear(tt->positions);
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ ERR_FAIL_COND_MSG(rt->compressed_track >= 0, "Compressed tracks can't be manually removed. Call clear() to get rid of compression first.");
_clear(rt->rotations);
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ ERR_FAIL_COND_MSG(st->compressed_track >= 0, "Compressed tracks can't be manually removed. Call clear() to get rid of compression first.");
_clear(st->scales);
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ ERR_FAIL_COND_MSG(bst->compressed_track >= 0, "Compressed tracks can't be manually removed. Call clear() to get rid of compression first.");
_clear(bst->blend_shapes);
} break;
@@ -837,9 +954,9 @@ NodePath Animation::track_get_path(int p_track) const {
return tracks[p_track]->path;
}
-int Animation::find_track(const NodePath &p_path) const {
+int Animation::find_track(const NodePath &p_path, const TrackType p_type) const {
for (int i = 0; i < tracks.size(); i++) {
- if (tracks[i]->path == p_path) {
+ if (tracks[i]->path == p_path && tracks[i]->type == p_type) {
return i;
}
};
@@ -907,6 +1024,8 @@ int Animation::position_track_insert_key(int p_track, double p_time, const Vecto
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ ERR_FAIL_COND_V(tt->compressed_track >= 0, -1);
+
TKey<Vector3> tkey;
tkey.time = p_time;
tkey.value = p_position;
@@ -922,6 +1041,19 @@ Error Animation::position_track_get_key(int p_track, int p_key, Vector3 *r_posit
PositionTrack *tt = static_cast<PositionTrack *>(t);
ERR_FAIL_COND_V(t->type != TYPE_POSITION_3D, ERR_INVALID_PARAMETER);
+
+ if (tt->compressed_track >= 0) {
+ Vector3i key;
+ double time;
+ bool fetch_success = _fetch_compressed_by_index<3>(tt->compressed_track, p_key, key, time);
+ if (!fetch_success) {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ *r_position = _uncompress_pos_scale(tt->compressed_track, key);
+ return OK;
+ }
+
ERR_FAIL_INDEX_V(p_key, tt->positions.size(), ERR_INVALID_PARAMETER);
*r_position = tt->positions[p_key].value;
@@ -936,6 +1068,14 @@ Error Animation::position_track_interpolate(int p_track, double p_time, Vector3
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ if (_pos_scale_interpolate_compressed(tt->compressed_track, p_time, *r_interpolation)) {
+ return OK;
+ } else {
+ return ERR_UNAVAILABLE;
+ }
+ }
+
bool ok = false;
Vector3 tk = _interpolate(tt->positions, p_time, tt->interpolation, tt->loop_wrap, &ok);
@@ -956,6 +1096,8 @@ int Animation::rotation_track_insert_key(int p_track, double p_time, const Quate
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ ERR_FAIL_COND_V(rt->compressed_track >= 0, -1);
+
TKey<Quaternion> tkey;
tkey.time = p_time;
tkey.value = p_rotation;
@@ -971,6 +1113,19 @@ Error Animation::rotation_track_get_key(int p_track, int p_key, Quaternion *r_ro
RotationTrack *rt = static_cast<RotationTrack *>(t);
ERR_FAIL_COND_V(t->type != TYPE_ROTATION_3D, ERR_INVALID_PARAMETER);
+
+ if (rt->compressed_track >= 0) {
+ Vector3i key;
+ double time;
+ bool fetch_success = _fetch_compressed_by_index<3>(rt->compressed_track, p_key, key, time);
+ if (!fetch_success) {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ *r_rotation = _uncompress_quaternion(key);
+ return OK;
+ }
+
ERR_FAIL_INDEX_V(p_key, rt->rotations.size(), ERR_INVALID_PARAMETER);
*r_rotation = rt->rotations[p_key].value;
@@ -985,6 +1140,14 @@ Error Animation::rotation_track_interpolate(int p_track, double p_time, Quaterni
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ if (_rotation_interpolate_compressed(rt->compressed_track, p_time, *r_interpolation)) {
+ return OK;
+ } else {
+ return ERR_UNAVAILABLE;
+ }
+ }
+
bool ok = false;
Quaternion tk = _interpolate(rt->rotations, p_time, rt->interpolation, rt->loop_wrap, &ok);
@@ -1005,6 +1168,8 @@ int Animation::scale_track_insert_key(int p_track, double p_time, const Vector3
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ ERR_FAIL_COND_V(st->compressed_track >= 0, -1);
+
TKey<Vector3> tkey;
tkey.time = p_time;
tkey.value = p_scale;
@@ -1020,6 +1185,19 @@ Error Animation::scale_track_get_key(int p_track, int p_key, Vector3 *r_scale) c
ScaleTrack *st = static_cast<ScaleTrack *>(t);
ERR_FAIL_COND_V(t->type != TYPE_SCALE_3D, ERR_INVALID_PARAMETER);
+
+ if (st->compressed_track >= 0) {
+ Vector3i key;
+ double time;
+ bool fetch_success = _fetch_compressed_by_index<3>(st->compressed_track, p_key, key, time);
+ if (!fetch_success) {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ *r_scale = _uncompress_pos_scale(st->compressed_track, key);
+ return OK;
+ }
+
ERR_FAIL_INDEX_V(p_key, st->scales.size(), ERR_INVALID_PARAMETER);
*r_scale = st->scales[p_key].value;
@@ -1034,6 +1212,14 @@ Error Animation::scale_track_interpolate(int p_track, double p_time, Vector3 *r_
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ if (_pos_scale_interpolate_compressed(st->compressed_track, p_time, *r_interpolation)) {
+ return OK;
+ } else {
+ return ERR_UNAVAILABLE;
+ }
+ }
+
bool ok = false;
Vector3 tk = _interpolate(st->scales, p_time, st->interpolation, st->loop_wrap, &ok);
@@ -1052,6 +1238,8 @@ int Animation::blend_shape_track_insert_key(int p_track, double p_time, float p_
BlendShapeTrack *st = static_cast<BlendShapeTrack *>(t);
+ ERR_FAIL_COND_V(st->compressed_track >= 0, -1);
+
TKey<float> tkey;
tkey.time = p_time;
tkey.value = p_blend_shape;
@@ -1065,11 +1253,24 @@ Error Animation::blend_shape_track_get_key(int p_track, int p_key, float *r_blen
ERR_FAIL_INDEX_V(p_track, tracks.size(), ERR_INVALID_PARAMETER);
Track *t = tracks[p_track];
- BlendShapeTrack *st = static_cast<BlendShapeTrack *>(t);
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
ERR_FAIL_COND_V(t->type != TYPE_BLEND_SHAPE, ERR_INVALID_PARAMETER);
- ERR_FAIL_INDEX_V(p_key, st->blend_shapes.size(), ERR_INVALID_PARAMETER);
- *r_blend_shape = st->blend_shapes[p_key].value;
+ if (bst->compressed_track >= 0) {
+ Vector3i key;
+ double time;
+ bool fetch_success = _fetch_compressed_by_index<1>(bst->compressed_track, p_key, key, time);
+ if (!fetch_success) {
+ return ERR_INVALID_PARAMETER;
+ }
+
+ *r_blend_shape = _uncompress_blend_shape(key);
+ return OK;
+ }
+
+ ERR_FAIL_INDEX_V(p_key, bst->blend_shapes.size(), ERR_INVALID_PARAMETER);
+
+ *r_blend_shape = bst->blend_shapes[p_key].value;
return OK;
}
@@ -1079,11 +1280,19 @@ Error Animation::blend_shape_track_interpolate(int p_track, double p_time, float
Track *t = tracks[p_track];
ERR_FAIL_COND_V(t->type != TYPE_BLEND_SHAPE, ERR_INVALID_PARAMETER);
- BlendShapeTrack *st = static_cast<BlendShapeTrack *>(t);
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+
+ if (bst->compressed_track >= 0) {
+ if (_blend_shape_interpolate_compressed(bst->compressed_track, p_time, *r_interpolation)) {
+ return OK;
+ } else {
+ return ERR_UNAVAILABLE;
+ }
+ }
bool ok = false;
- float tk = _interpolate(st->blend_shapes, p_time, st->interpolation, st->loop_wrap, &ok);
+ float tk = _interpolate(bst->blend_shapes, p_time, bst->interpolation, bst->loop_wrap, &ok);
if (!ok) {
return ERR_UNAVAILABLE;
@@ -1105,24 +1314,36 @@ void Animation::track_remove_key(int p_track, int p_idx) {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+
+ ERR_FAIL_COND(tt->compressed_track >= 0);
+
ERR_FAIL_INDEX(p_idx, tt->positions.size());
tt->positions.remove(p_idx);
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+
+ ERR_FAIL_COND(rt->compressed_track >= 0);
+
ERR_FAIL_INDEX(p_idx, rt->rotations.size());
rt->rotations.remove(p_idx);
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+
+ ERR_FAIL_COND(st->compressed_track >= 0);
+
ERR_FAIL_INDEX(p_idx, st->scales.size());
st->scales.remove(p_idx);
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+
+ ERR_FAIL_COND(bst->compressed_track >= 0);
+
ERR_FAIL_INDEX(p_idx, bst->blend_shapes.size());
bst->blend_shapes.remove(p_idx);
@@ -1169,6 +1390,21 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+
+ if (tt->compressed_track >= 0) {
+ double time;
+ double time_next;
+ Vector3i key;
+ Vector3i key_next;
+ uint32_t key_index;
+ bool fetch_compressed_success = _fetch_compressed<3>(tt->compressed_track, p_time, key, time, key_next, time_next, &key_index);
+ ERR_FAIL_COND_V(!fetch_compressed_success, -1);
+ if (p_exact && time != p_time) {
+ return -1;
+ }
+ return key_index;
+ }
+
int k = _find(tt->positions, p_time);
if (k < 0 || k >= tt->positions.size()) {
return -1;
@@ -1181,6 +1417,21 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+
+ if (rt->compressed_track >= 0) {
+ double time;
+ double time_next;
+ Vector3i key;
+ Vector3i key_next;
+ uint32_t key_index;
+ bool fetch_compressed_success = _fetch_compressed<3>(rt->compressed_track, p_time, key, time, key_next, time_next, &key_index);
+ ERR_FAIL_COND_V(!fetch_compressed_success, -1);
+ if (p_exact && time != p_time) {
+ return -1;
+ }
+ return key_index;
+ }
+
int k = _find(rt->rotations, p_time);
if (k < 0 || k >= rt->rotations.size()) {
return -1;
@@ -1193,6 +1444,21 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+
+ if (st->compressed_track >= 0) {
+ double time;
+ double time_next;
+ Vector3i key;
+ Vector3i key_next;
+ uint32_t key_index;
+ bool fetch_compressed_success = _fetch_compressed<3>(st->compressed_track, p_time, key, time, key_next, time_next, &key_index);
+ ERR_FAIL_COND_V(!fetch_compressed_success, -1);
+ if (p_exact && time != p_time) {
+ return -1;
+ }
+ return key_index;
+ }
+
int k = _find(st->scales, p_time);
if (k < 0 || k >= st->scales.size()) {
return -1;
@@ -1205,6 +1471,21 @@ int Animation::track_find_key(int p_track, double p_time, bool p_exact) const {
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+
+ if (bst->compressed_track >= 0) {
+ double time;
+ double time_next;
+ Vector3i key;
+ Vector3i key_next;
+ uint32_t key_index;
+ bool fetch_compressed_success = _fetch_compressed<1>(bst->compressed_track, p_time, key, time, key_next, time_next, &key_index);
+ ERR_FAIL_COND_V(!fetch_compressed_success, -1);
+ if (p_exact && time != p_time) {
+ return -1;
+ }
+ return key_index;
+ }
+
int k = _find(bst->blend_shapes, p_time);
if (k < 0 || k >= bst->blend_shapes.size()) {
return -1;
@@ -1392,18 +1673,30 @@ int Animation::track_get_key_count(int p_track) const {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ return _get_compressed_key_count(tt->compressed_track);
+ }
return tt->positions.size();
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ return _get_compressed_key_count(rt->compressed_track);
+ }
return rt->rotations.size();
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ return _get_compressed_key_count(st->compressed_track);
+ }
return st->scales.size();
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ if (bst->compressed_track >= 0) {
+ return _get_compressed_key_count(bst->compressed_track);
+ }
return bst->blend_shapes.size();
} break;
case TYPE_VALUE: {
@@ -1438,28 +1731,24 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const {
switch (t->type) {
case TYPE_POSITION_3D: {
- PositionTrack *tt = static_cast<PositionTrack *>(t);
- ERR_FAIL_INDEX_V(p_key_idx, tt->positions.size(), Variant());
-
- return tt->positions[p_key_idx].value;
+ Vector3 value;
+ position_track_get_key(p_track, p_key_idx, &value);
+ return value;
} break;
case TYPE_ROTATION_3D: {
- RotationTrack *rt = static_cast<RotationTrack *>(t);
- ERR_FAIL_INDEX_V(p_key_idx, rt->rotations.size(), Variant());
-
- return rt->rotations[p_key_idx].value;
+ Quaternion value;
+ rotation_track_get_key(p_track, p_key_idx, &value);
+ return value;
} break;
case TYPE_SCALE_3D: {
- ScaleTrack *st = static_cast<ScaleTrack *>(t);
- ERR_FAIL_INDEX_V(p_key_idx, st->scales.size(), Variant());
-
- return st->scales[p_key_idx].value;
+ Vector3 value;
+ scale_track_get_key(p_track, p_key_idx, &value);
+ return value;
} break;
case TYPE_BLEND_SHAPE: {
- BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
- ERR_FAIL_INDEX_V(p_key_idx, bst->blend_shapes.size(), Variant());
-
- return bst->blend_shapes[p_key_idx].value;
+ float value;
+ blend_shape_track_get_key(p_track, p_key_idx, &value);
+ return value;
} break;
case TYPE_VALUE: {
ValueTrack *vt = static_cast<ValueTrack *>(t);
@@ -1520,21 +1809,49 @@ double Animation::track_get_key_time(int p_track, int p_key_idx) const {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ Vector3i value;
+ double time;
+ bool fetch_compressed_success = _fetch_compressed_by_index<3>(tt->compressed_track, p_key_idx, value, time);
+ ERR_FAIL_COND_V(!fetch_compressed_success, false);
+ return time;
+ }
ERR_FAIL_INDEX_V(p_key_idx, tt->positions.size(), -1);
return tt->positions[p_key_idx].time;
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ Vector3i value;
+ double time;
+ bool fetch_compressed_success = _fetch_compressed_by_index<3>(rt->compressed_track, p_key_idx, value, time);
+ ERR_FAIL_COND_V(!fetch_compressed_success, false);
+ return time;
+ }
ERR_FAIL_INDEX_V(p_key_idx, rt->rotations.size(), -1);
return rt->rotations[p_key_idx].time;
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ Vector3i value;
+ double time;
+ bool fetch_compressed_success = _fetch_compressed_by_index<3>(st->compressed_track, p_key_idx, value, time);
+ ERR_FAIL_COND_V(!fetch_compressed_success, false);
+ return time;
+ }
ERR_FAIL_INDEX_V(p_key_idx, st->scales.size(), -1);
return st->scales[p_key_idx].time;
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ if (bst->compressed_track >= 0) {
+ Vector3i value;
+ double time;
+ bool fetch_compressed_success = _fetch_compressed_by_index<1>(bst->compressed_track, p_key_idx, value, time);
+ ERR_FAIL_COND_V(!fetch_compressed_success, false);
+ return time;
+ }
ERR_FAIL_INDEX_V(p_key_idx, bst->blend_shapes.size(), -1);
return bst->blend_shapes[p_key_idx].time;
} break;
@@ -1580,6 +1897,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->positions.size());
TKey<Vector3> key = tt->positions[p_key_idx];
key.time = p_time;
@@ -1589,6 +1907,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) {
}
case TYPE_ROTATION_3D: {
RotationTrack *tt = static_cast<RotationTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->rotations.size());
TKey<Quaternion> key = tt->rotations[p_key_idx];
key.time = p_time;
@@ -1598,6 +1917,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) {
}
case TYPE_SCALE_3D: {
ScaleTrack *tt = static_cast<ScaleTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->scales.size());
TKey<Vector3> key = tt->scales[p_key_idx];
key.time = p_time;
@@ -1607,6 +1927,7 @@ void Animation::track_set_key_time(int p_track, int p_key_idx, double p_time) {
}
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *tt = static_cast<BlendShapeTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->blend_shapes.size());
TKey<float> key = tt->blend_shapes[p_key_idx];
key.time = p_time;
@@ -1671,21 +1992,33 @@ real_t Animation::track_get_key_transition(int p_track, int p_key_idx) const {
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ if (tt->compressed_track >= 0) {
+ return 1.0;
+ }
ERR_FAIL_INDEX_V(p_key_idx, tt->positions.size(), -1);
return tt->positions[p_key_idx].transition;
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ if (rt->compressed_track >= 0) {
+ return 1.0;
+ }
ERR_FAIL_INDEX_V(p_key_idx, rt->rotations.size(), -1);
return rt->rotations[p_key_idx].transition;
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ if (st->compressed_track >= 0) {
+ return 1.0;
+ }
ERR_FAIL_INDEX_V(p_key_idx, st->scales.size(), -1);
return st->scales[p_key_idx].transition;
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ if (bst->compressed_track >= 0) {
+ return 1.0;
+ }
ERR_FAIL_INDEX_V(p_key_idx, bst->blend_shapes.size(), -1);
return bst->blend_shapes[p_key_idx].transition;
} break;
@@ -1715,6 +2048,35 @@ real_t Animation::track_get_key_transition(int p_track, int p_key_idx) const {
ERR_FAIL_V(0);
}
+bool Animation::track_is_compressed(int p_track) const {
+ ERR_FAIL_INDEX_V(p_track, tracks.size(), false);
+ Track *t = tracks[p_track];
+
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ PositionTrack *tt = static_cast<PositionTrack *>(t);
+ return tt->compressed_track >= 0;
+ } break;
+ case TYPE_ROTATION_3D: {
+ RotationTrack *rt = static_cast<RotationTrack *>(t);
+ return rt->compressed_track >= 0;
+ } break;
+ case TYPE_SCALE_3D: {
+ ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ return st->compressed_track >= 0;
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ return bst->compressed_track >= 0;
+ } break;
+ default: {
+ return false; //animation does not really use transitions
+ } break;
+ }
+
+ ERR_FAIL_V(false);
+}
+
void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p_value) {
ERR_FAIL_INDEX(p_track, tracks.size());
Track *t = tracks[p_track];
@@ -1723,6 +2085,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
case TYPE_POSITION_3D: {
ERR_FAIL_COND((p_value.get_type() != Variant::VECTOR3) && (p_value.get_type() != Variant::VECTOR3I));
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->positions.size());
tt->positions.write[p_key_idx].value = p_value;
@@ -1731,6 +2094,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
case TYPE_ROTATION_3D: {
ERR_FAIL_COND((p_value.get_type() != Variant::QUATERNION) && (p_value.get_type() != Variant::BASIS));
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ ERR_FAIL_COND(rt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, rt->rotations.size());
rt->rotations.write[p_key_idx].value = p_value;
@@ -1739,6 +2103,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
case TYPE_SCALE_3D: {
ERR_FAIL_COND((p_value.get_type() != Variant::VECTOR3) && (p_value.get_type() != Variant::VECTOR3I));
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ ERR_FAIL_COND(st->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, st->scales.size());
st->scales.write[p_key_idx].value = p_value;
@@ -1747,6 +2112,7 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
case TYPE_BLEND_SHAPE: {
ERR_FAIL_COND((p_value.get_type() != Variant::FLOAT) && (p_value.get_type() != Variant::INT));
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ ERR_FAIL_COND(bst->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, bst->blend_shapes.size());
bst->blend_shapes.write[p_key_idx].value = p_value;
@@ -1820,21 +2186,25 @@ void Animation::track_set_key_transition(int p_track, int p_key_idx, real_t p_tr
switch (t->type) {
case TYPE_POSITION_3D: {
PositionTrack *tt = static_cast<PositionTrack *>(t);
+ ERR_FAIL_COND(tt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, tt->positions.size());
tt->positions.write[p_key_idx].transition = p_transition;
} break;
case TYPE_ROTATION_3D: {
RotationTrack *rt = static_cast<RotationTrack *>(t);
+ ERR_FAIL_COND(rt->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, rt->rotations.size());
rt->rotations.write[p_key_idx].transition = p_transition;
} break;
case TYPE_SCALE_3D: {
ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ ERR_FAIL_COND(st->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, st->scales.size());
st->scales.write[p_key_idx].transition = p_transition;
} break;
case TYPE_BLEND_SHAPE: {
BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ ERR_FAIL_COND(bst->compressed_track >= 0);
ERR_FAIL_INDEX(p_key_idx, bst->blend_shapes.size());
bst->blend_shapes.write[p_key_idx].transition = p_transition;
} break;
@@ -2334,26 +2704,50 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
switch (t->type) {
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
- _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
- _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices);
+ if (tt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices);
+
+ } else {
+ _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices);
+ _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices);
+ }
} break;
case TYPE_ROTATION_3D: {
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
- _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
- _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices);
+ if (rt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices);
+
+ } else {
+ _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices);
+ _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices);
+ }
} break;
case TYPE_SCALE_3D: {
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
- _track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
- _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices);
+ if (st->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices);
+
+ } else {
+ _track_get_key_indices_in_range(st->scales, from_time, length, p_indices);
+ _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices);
+ }
} break;
case TYPE_BLEND_SHAPE: {
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
- _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
- _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices);
+ if (bst->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices);
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices);
+
+ } else {
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices);
+ _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices);
+ }
} break;
case TYPE_VALUE: {
@@ -2408,22 +2802,38 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl
switch (t->type) {
case TYPE_POSITION_3D: {
const PositionTrack *tt = static_cast<const PositionTrack *>(t);
- _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices);
+ if (tt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, to_time - from_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices);
+ }
} break;
case TYPE_ROTATION_3D: {
const RotationTrack *rt = static_cast<const RotationTrack *>(t);
- _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices);
+ if (rt->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, to_time - from_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices);
+ }
} break;
case TYPE_SCALE_3D: {
const ScaleTrack *st = static_cast<const ScaleTrack *>(t);
- _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices);
+ if (st->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, to_time - from_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices);
+ }
} break;
case TYPE_BLEND_SHAPE: {
const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t);
- _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices);
+ if (bst->compressed_track >= 0) {
+ _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, to_time - from_time, p_indices);
+ } else {
+ _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices);
+ }
} break;
case TYPE_VALUE: {
@@ -3027,7 +3437,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_get_type", "track_idx"), &Animation::track_get_type);
ClassDB::bind_method(D_METHOD("track_get_path", "track_idx"), &Animation::track_get_path);
ClassDB::bind_method(D_METHOD("track_set_path", "track_idx", "path"), &Animation::track_set_path);
- ClassDB::bind_method(D_METHOD("find_track", "path"), &Animation::find_track);
+ ClassDB::bind_method(D_METHOD("find_track", "path", "type"), &Animation::find_track);
ClassDB::bind_method(D_METHOD("track_move_up", "track_idx"), &Animation::track_move_up);
ClassDB::bind_method(D_METHOD("track_move_down", "track_idx"), &Animation::track_move_down);
@@ -3064,6 +3474,8 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("track_set_interpolation_loop_wrap", "track_idx", "interpolation"), &Animation::track_set_interpolation_loop_wrap);
ClassDB::bind_method(D_METHOD("track_get_interpolation_loop_wrap", "track_idx"), &Animation::track_get_interpolation_loop_wrap);
+ ClassDB::bind_method(D_METHOD("track_is_compressed", "track_idx"), &Animation::track_is_compressed);
+
ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode);
ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode);
@@ -3110,6 +3522,8 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &Animation::clear);
ClassDB::bind_method(D_METHOD("copy_track", "track_idx", "to_animation"), &Animation::copy_track);
+ ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0));
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step");
@@ -3143,6 +3557,10 @@ void Animation::clear() {
tracks.clear();
loop = false;
length = 1;
+ compression.enabled = false;
+ compression.bounds.clear();
+ compression.pages.clear();
+ compression.fps = 120;
emit_changed();
emit_signal(SceneStringNames::get_singleton()->tracks_changed);
}
@@ -3447,6 +3865,9 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_linear_e
void Animation::optimize(real_t p_allowed_linear_err, real_t p_allowed_angular_err, real_t p_max_optimizable_angle) {
for (int i = 0; i < tracks.size(); i++) {
+ if (track_is_compressed(i)) {
+ continue; //not possible to optimize compressed track
+ }
if (tracks[i]->type == TYPE_POSITION_3D) {
_position_track_optimize(i, p_allowed_linear_err, p_allowed_angular_err);
} else if (tracks[i]->type == TYPE_ROTATION_3D) {
@@ -3459,6 +3880,1154 @@ void Animation::optimize(real_t p_allowed_linear_err, real_t p_allowed_angular_e
}
}
+#define print_animc(m_str)
+//#define print_animc(m_str) print_line(m_str);
+
+struct AnimationCompressionDataState {
+ enum {
+ MIN_OPTIMIZE_PACKETS = 5,
+ MAX_PACKETS = 16
+ };
+
+ uint32_t components = 3;
+ LocalVector<uint8_t> data; //commited packets
+ struct PacketData {
+ int32_t data[3] = { 0, 0, 0 };
+ uint32_t frame = 0;
+ };
+
+ float split_tolerance = 1.5;
+
+ LocalVector<PacketData> temp_packets;
+
+ //used for rollback if the new frame does not fit
+ int32_t validated_packet_count = -1;
+
+ static int32_t _compute_delta16_signed(int32_t p_from, int32_t p_to) {
+ int32_t delta = p_to - p_from;
+ if (delta > 32767) {
+ return delta - 65536; // use wrap around
+ } else if (delta < -32768) {
+ return 65536 + delta; // use wrap around
+ }
+ return delta;
+ }
+
+ static uint32_t _compute_shift_bits_signed(int32_t p_delta) {
+ if (p_delta == 0) {
+ return 0;
+ } else if (p_delta < 0) {
+ p_delta = ABS(p_delta) - 1;
+ if (p_delta == 0) {
+ return 1;
+ }
+ }
+ return nearest_shift(p_delta);
+ }
+
+ void _compute_max_shifts(uint32_t p_from, uint32_t p_to, uint32_t *max_shifts, uint32_t &max_frame_delta_shift) const {
+ for (uint32_t j = 0; j < components; j++) {
+ max_shifts[j] = 0;
+ }
+ max_frame_delta_shift = 0;
+
+ for (uint32_t i = p_from + 1; i <= p_to; i++) {
+ int32_t frame_delta = temp_packets[i].frame - temp_packets[i - 1].frame;
+ max_frame_delta_shift = MAX(max_frame_delta_shift, nearest_shift(frame_delta));
+ for (uint32_t j = 0; j < components; j++) {
+ int32_t diff = _compute_delta16_signed(temp_packets[i - 1].data[j], temp_packets[i].data[j]);
+ uint32_t shift = _compute_shift_bits_signed(diff);
+ max_shifts[j] = MAX(shift, max_shifts[j]);
+ }
+ }
+ }
+
+ bool insert_key(uint32_t p_frame, const Vector3i &p_key) {
+ if (temp_packets.size() == MAX_PACKETS) {
+ commit_temp_packets();
+ }
+ PacketData packet;
+ packet.frame = p_frame;
+ for (int i = 0; i < 3; i++) {
+ ERR_FAIL_COND_V(p_key[i] > 65535, false); // Sanity check
+ packet.data[i] = p_key[i];
+ }
+
+ temp_packets.push_back(packet);
+
+ if (temp_packets.size() >= MIN_OPTIMIZE_PACKETS) {
+ uint32_t max_shifts[3] = { 0, 0, 0 }; // Base sizes, 16 bit
+ uint32_t max_frame_delta_shift = 0;
+ // Compute the average shift before the packet was added
+ _compute_max_shifts(0, temp_packets.size() - 2, max_shifts, max_frame_delta_shift);
+
+ float prev_packet_size_avg = 0;
+ prev_packet_size_avg = float(1 << max_frame_delta_shift);
+ for (uint32_t i = 0; i < components; i++) {
+ prev_packet_size_avg += float(1 << max_shifts[i]);
+ }
+ prev_packet_size_avg /= float(1 + components);
+
+ _compute_max_shifts(temp_packets.size() - 2, temp_packets.size() - 1, max_shifts, max_frame_delta_shift);
+
+ float new_packet_size_avg = 0;
+ new_packet_size_avg = float(1 << max_frame_delta_shift);
+ for (uint32_t i = 0; i < components; i++) {
+ new_packet_size_avg += float(1 << max_shifts[i]);
+ }
+ new_packet_size_avg /= float(1 + components);
+
+ print_animc("packet count: " + rtos(temp_packets.size() - 1) + " size avg " + rtos(prev_packet_size_avg) + " new avg " + rtos(new_packet_size_avg));
+ float ratio = (prev_packet_size_avg < new_packet_size_avg) ? (new_packet_size_avg / prev_packet_size_avg) : (prev_packet_size_avg / new_packet_size_avg);
+
+ if (ratio > split_tolerance) {
+ print_animc("split!");
+ temp_packets.resize(temp_packets.size() - 1);
+ commit_temp_packets();
+ temp_packets.push_back(packet);
+ }
+ }
+
+ return temp_packets.size() == 1; // First key
+ }
+
+ uint32_t get_temp_packet_size() const {
+ if (temp_packets.size() == 0) {
+ return 0;
+ } else if (temp_packets.size() == 1) {
+ return components == 1 ? 4 : 8; // 1 component packet is 16 bits and 16 bits unused. 3 component packets is 48 bits and 16 bits unused
+ }
+ uint32_t max_shifts[3] = { 0, 0, 0 }; //base sizes, 16 bit
+ uint32_t max_frame_delta_shift = 0;
+
+ _compute_max_shifts(0, temp_packets.size() - 1, max_shifts, max_frame_delta_shift);
+
+ uint32_t size_bits = 16; //base value (all 4 bits of shift sizes for x,y,z,time)
+ size_bits += max_frame_delta_shift * (temp_packets.size() - 1); //times
+ for (uint32_t j = 0; j < components; j++) {
+ size_bits += 16; //base value
+ uint32_t shift = max_shifts[j];
+ if (shift > 0) {
+ shift += 1; //if not zero, add sign bit
+ }
+ size_bits += shift * (temp_packets.size() - 1);
+ }
+ if (size_bits % 8 != 0) { //wrap to 8 bits
+ size_bits += 8 - (size_bits % 8);
+ }
+ uint32_t size_bytes = size_bits / 8; //wrap to words
+ if (size_bytes % 4 != 0) {
+ size_bytes += 4 - (size_bytes % 4);
+ }
+ return size_bytes;
+ }
+
+ static void _push_bits(LocalVector<uint8_t> &data, uint32_t &r_buffer, uint32_t &r_bits_used, uint32_t p_value, uint32_t p_bits) {
+ r_buffer |= p_value << r_bits_used;
+ r_bits_used += p_bits;
+ while (r_bits_used >= 8) {
+ uint8_t byte = r_buffer & 0xFF;
+ data.push_back(byte);
+ r_buffer >>= 8;
+ r_bits_used -= 8;
+ }
+ }
+
+ void commit_temp_packets() {
+ if (temp_packets.size() == 0) {
+ return; //nohing to do
+ }
+#define DEBUG_PACKET_PUSH
+#ifdef DEBUG_PACKET_PUSH
+#ifndef _MSC_VER
+#warning Debugging packet push, disable this code in production to gain a bit more import performance.
+#endif
+ uint32_t debug_packet_push = get_temp_packet_size();
+ uint32_t debug_data_size = data.size();
+#endif
+ // Store header
+
+ uint8_t header[8];
+ uint32_t header_bytes = 0;
+ for (uint32_t i = 0; i < components; i++) {
+ encode_uint16(temp_packets[0].data[i], &header[header_bytes]);
+ header_bytes += 2;
+ }
+
+ uint32_t max_shifts[3] = { 0, 0, 0 }; //base sizes, 16 bit
+ uint32_t max_frame_delta_shift = 0;
+
+ if (temp_packets.size() > 1) {
+ _compute_max_shifts(0, temp_packets.size() - 1, max_shifts, max_frame_delta_shift);
+ uint16_t shift_header = (max_frame_delta_shift - 1) << 12;
+ for (uint32_t i = 0; i < components; i++) {
+ shift_header |= max_shifts[i] << (4 * i);
+ }
+
+ encode_uint16(shift_header, &header[header_bytes]);
+ header_bytes += 2;
+ }
+
+ while (header_bytes % 4 != 0) {
+ header[header_bytes++] = 0;
+ }
+
+ for (uint32_t i = 0; i < header_bytes; i++) {
+ data.push_back(header[i]);
+ }
+
+ if (temp_packets.size() == 1) {
+ temp_packets.clear();
+ validated_packet_count = 0;
+ return; //only header stored, nothing else to do
+ }
+
+ uint32_t bit_buffer = 0;
+ uint32_t bits_used = 0;
+
+ for (uint32_t i = 1; i < temp_packets.size(); i++) {
+ uint32_t frame_delta = temp_packets[i].frame - temp_packets[i - 1].frame;
+ _push_bits(data, bit_buffer, bits_used, frame_delta, max_frame_delta_shift);
+
+ for (uint32_t j = 0; j < components; j++) {
+ if (max_shifts[j] == 0) {
+ continue; // Zero delta, do not store
+ }
+ int32_t delta = _compute_delta16_signed(temp_packets[i - 1].data[j], temp_packets[i].data[j]);
+
+ ERR_FAIL_COND(delta < -32768 || delta > 32767); //sanity check
+
+ uint16_t deltau;
+ if (delta < 0) {
+ deltau = (ABS(delta) - 1) | (1 << max_shifts[j]);
+ } else {
+ deltau = delta;
+ }
+ _push_bits(data, bit_buffer, bits_used, deltau, max_shifts[j] + 1); // Include sign bit
+ }
+ }
+ if (bits_used != 0) {
+ ERR_FAIL_COND(bit_buffer > 0xFF); // Sanity check
+ data.push_back(bit_buffer);
+ }
+
+ while (data.size() % 4 != 0) {
+ data.push_back(0); //pad to align with 4
+ }
+
+ temp_packets.clear();
+ validated_packet_count = 0;
+
+#ifdef DEBUG_PACKET_PUSH
+ ERR_FAIL_COND((data.size() - debug_data_size) != debug_packet_push);
+#endif
+ }
+};
+
+struct AnimationCompressionTimeState {
+ struct Packet {
+ uint32_t frame;
+ uint32_t offset;
+ uint32_t count;
+ };
+
+ LocalVector<Packet> packets;
+ //used for rollback
+ int32_t key_index = 0;
+ int32_t validated_packet_count = 0;
+ int32_t validated_key_index = -1;
+ bool needs_start_frame = false;
+};
+
+Vector3i Animation::_compress_key(uint32_t p_track, const AABB &p_bounds, int32_t p_key, float p_time) {
+ Vector3i values;
+ TrackType tt = track_get_type(p_track);
+ switch (tt) {
+ case TYPE_POSITION_3D: {
+ Vector3 pos;
+ if (p_key >= 0) {
+ position_track_get_key(p_track, p_key, &pos);
+ } else {
+ position_track_interpolate(p_track, p_time, &pos);
+ }
+ pos = (pos - p_bounds.position) / p_bounds.size;
+ for (int j = 0; j < 3; j++) {
+ values[j] = CLAMP(int32_t(pos[j] * 65535.0), 0, 65535);
+ }
+ } break;
+ case TYPE_ROTATION_3D: {
+ Quaternion rot;
+ if (p_key >= 0) {
+ rotation_track_get_key(p_track, p_key, &rot);
+ } else {
+ rotation_track_interpolate(p_track, p_time, &rot);
+ }
+ Vector3 axis = rot.get_axis();
+ float angle = rot.get_angle();
+ angle = Math::fposmod(double(angle), double(Math_PI * 2.0));
+ Vector2 oct = axis.octahedron_encode();
+ Vector3 rot_norm(oct.x, oct.y, angle / (Math_PI * 2.0)); // high resolution rotation in 0-1 angle.
+
+ for (int j = 0; j < 3; j++) {
+ values[j] = CLAMP(int32_t(rot_norm[j] * 65535.0), 0, 65535);
+ }
+ } break;
+ case TYPE_SCALE_3D: {
+ Vector3 scale;
+ if (p_key >= 0) {
+ scale_track_get_key(p_track, p_key, &scale);
+ } else {
+ scale_track_interpolate(p_track, p_time, &scale);
+ }
+ scale = (scale - p_bounds.position) / p_bounds.size;
+ for (int j = 0; j < 3; j++) {
+ values[j] = CLAMP(int32_t(scale[j] * 65535.0), 0, 65535);
+ }
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ float blend;
+ if (p_key >= 0) {
+ blend_shape_track_get_key(p_track, p_key, &blend);
+ } else {
+ blend_shape_track_interpolate(p_track, p_time, &blend);
+ }
+
+ blend = (blend / float(Compression::BLEND_SHAPE_RANGE)) * 0.5 + 0.5;
+ values[0] = CLAMP(int32_t(blend * 65535.0), 0, 65535);
+ } break;
+ default: {
+ ERR_FAIL_V(Vector3i()); //sanity check
+ } break;
+ }
+
+ return values;
+}
+
+struct AnimationCompressionBufferBitsRead {
+ uint32_t buffer = 0;
+ uint32_t used = 0;
+ const uint8_t *src_data = nullptr;
+
+ _FORCE_INLINE_ uint32_t read(uint32_t p_bits) {
+ uint32_t output = 0;
+ uint32_t written = 0;
+ while (p_bits > 0) {
+ if (used == 0) {
+ used = 8;
+ buffer = *src_data;
+ src_data++;
+ }
+ uint32_t to_write = MIN(used, p_bits);
+ output |= (buffer & ((1 << to_write) - 1)) << written;
+ buffer >>= to_write;
+ used -= to_write;
+ p_bits -= to_write;
+ written += to_write;
+ }
+ return output;
+ }
+};
+
+void Animation::compress(uint32_t p_page_size, uint32_t p_fps, float p_split_tolerance) {
+ ERR_FAIL_COND_MSG(compression.enabled, "This animation is already compressed");
+
+ p_split_tolerance = CLAMP(p_split_tolerance, 1.1, 8.0);
+ compression.pages.clear();
+
+ uint32_t base_page_size = 0; // Before compressing pages, compute how large the "end page" datablock is.
+ LocalVector<uint32_t> tracks_to_compress;
+ LocalVector<AABB> track_bounds;
+ const uint32_t time_packet_size = 4;
+
+ const uint32_t track_header_size = 4 + 4 + 4; // pointer to time (4 bytes), amount of time keys (4 bytes) pointer to track data (4 bytes)
+
+ for (int i = 0; i < get_track_count(); i++) {
+ TrackType type = track_get_type(i);
+ if (type != TYPE_POSITION_3D && type != TYPE_ROTATION_3D && type != TYPE_SCALE_3D && type != TYPE_BLEND_SHAPE) {
+ continue;
+ }
+ if (track_get_key_count(i) == 0) {
+ continue; //do not compress, no keys
+ }
+ base_page_size += track_header_size; //pointer to beginning of each track timeline and amount of time keys
+ base_page_size += time_packet_size; //for end of track time marker
+ base_page_size += (type == TYPE_BLEND_SHAPE) ? 4 : 8; // at least the end of track packet (at much 8 bytes). This could be less, but have to be pessimistic.
+ tracks_to_compress.push_back(i);
+
+ AABB bounds;
+
+ if (type == TYPE_POSITION_3D) {
+ AABB aabb;
+ int kcount = track_get_key_count(i);
+ for (int j = 0; j < kcount; j++) {
+ Vector3 pos;
+ position_track_get_key(i, j, &pos);
+ if (j == 0) {
+ aabb.position = pos;
+ } else {
+ aabb.expand_to(pos);
+ }
+ }
+ for (int j = 0; j < 3; j++) {
+ //cant have zero
+ if (aabb.size[j] < CMP_EPSILON) {
+ aabb.size[j] = CMP_EPSILON;
+ }
+ }
+ bounds = aabb;
+ }
+ if (type == TYPE_SCALE_3D) {
+ AABB aabb;
+ int kcount = track_get_key_count(i);
+ for (int j = 0; j < kcount; j++) {
+ Vector3 scale;
+ scale_track_get_key(i, j, &scale);
+ if (j == 0) {
+ aabb.position = scale;
+ } else {
+ aabb.expand_to(scale);
+ }
+ }
+ for (int j = 0; j < 3; j++) {
+ //cant have zero
+ if (aabb.size[j] < CMP_EPSILON) {
+ aabb.size[j] = CMP_EPSILON;
+ }
+ }
+ bounds = aabb;
+ }
+
+ track_bounds.push_back(bounds);
+ }
+
+ if (tracks_to_compress.size() == 0) {
+ return; //nothing to compress
+ }
+
+ print_animc("Anim Compression:");
+ print_animc("-----------------");
+ print_animc("Tracks to compress: " + itos(tracks_to_compress.size()));
+
+ uint32_t current_frame = 0;
+ uint32_t base_page_frame = 0;
+ double frame_len = 1.0 / double(p_fps);
+ const uint32_t max_frames_per_page = 65536;
+
+ print_animc("Frame Len: " + rtos(frame_len));
+
+ LocalVector<AnimationCompressionDataState> data_tracks;
+ LocalVector<AnimationCompressionTimeState> time_tracks;
+
+ data_tracks.resize(tracks_to_compress.size());
+ time_tracks.resize(tracks_to_compress.size());
+
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ data_tracks[i].split_tolerance = p_split_tolerance;
+ if (track_get_type(tracks_to_compress[i]) == TYPE_BLEND_SHAPE) {
+ data_tracks[i].components = 1;
+ } else {
+ data_tracks[i].components = 3;
+ }
+ }
+
+ while (true) {
+ // Begin by finding the keyframe in all tracks with the time closest to the current time
+ const uint32_t FRAME_MAX = 0xFFFFFFFF;
+ const int32_t NO_TRACK_FOUND = -1;
+ uint32_t best_frame = FRAME_MAX;
+ uint32_t best_invalid_frame = FRAME_MAX;
+ int32_t best_frame_track = NO_TRACK_FOUND; // Default is -1, which means all keyframes for this page are exhausted.
+ bool start_frame = false;
+
+ for (uint32_t i = 0; i < tracks_to_compress.size(); i++) {
+ uint32_t uncomp_track = tracks_to_compress[i];
+
+ if (time_tracks[i].key_index == track_get_key_count(uncomp_track)) {
+ if (time_tracks[i].needs_start_frame) {
+ start_frame = true;
+ best_frame = base_page_frame;
+ best_frame_track = i;
+ time_tracks[i].needs_start_frame = false;
+ break;
+ } else {
+ continue; // This track is exhausted (all keys were added already), don't consider.
+ }
+ }
+
+ uint32_t key_frame = double(track_get_key_time(uncomp_track, time_tracks[i].key_index)) / frame_len;
+
+ if (time_tracks[i].needs_start_frame && key_frame > base_page_frame) {
+ start_frame = true;
+ best_frame = base_page_frame;
+ best_frame_track = i;
+ time_tracks[i].needs_start_frame = false;
+ break;
+ }
+
+ ERR_FAIL_COND(key_frame < base_page_frame); // Sanity check, should never happen
+
+ if (key_frame - base_page_frame >= max_frames_per_page) {
+ // Invalid because beyond the max frames allowed per page
+ best_invalid_frame = MIN(best_invalid_frame, key_frame);
+ } else if (key_frame < best_frame) {
+ best_frame = key_frame;
+ best_frame_track = i;
+ }
+ }
+
+ print_animc("*KEY*: Current Frame: " + itos(current_frame) + " Best Frame: " + rtos(best_frame) + " Best Track: " + itos(best_frame_track) + " Start: " + String(start_frame ? "true" : "false"));
+
+ if (!start_frame && best_frame > current_frame) {
+ // Any case where the current frame advanced, either because nothing was found or because something was found greater than the current one.
+ print_animc("\tAdvance Condition.");
+ bool rollback = false;
+
+ // The frame has advanced, time to validate the previous frame
+ uint32_t current_page_size = base_page_size;
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ uint32_t track_size = data_tracks[i].data.size(); // track size
+ track_size += data_tracks[i].get_temp_packet_size(); // Add the temporary data
+ if (track_size > Compression::MAX_DATA_TRACK_SIZE) {
+ rollback = true; //track to large, time track can't point to keys any longer, because key offset is 12 bits
+ break;
+ }
+ current_page_size += track_size;
+ }
+ for (uint32_t i = 0; i < time_tracks.size(); i++) {
+ current_page_size += time_tracks[i].packets.size() * 4; // time packet is 32 bits
+ }
+
+ if (!rollback && current_page_size > p_page_size) {
+ rollback = true;
+ }
+
+ print_animc("\tCurrent Page Size: " + itos(current_page_size) + "/" + itos(p_page_size) + " Rollback? " + String(rollback ? "YES!" : "no"));
+
+ if (rollback) {
+ // Not valid any longer, so rollback and commit page
+
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ data_tracks[i].temp_packets.resize(data_tracks[i].validated_packet_count);
+ }
+ for (uint32_t i = 0; i < time_tracks.size(); i++) {
+ time_tracks[i].key_index = time_tracks[i].validated_key_index; //rollback key
+ time_tracks[i].packets.resize(time_tracks[i].validated_packet_count);
+ }
+
+ } else {
+ // All valid, so save rollback information
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ data_tracks[i].validated_packet_count = data_tracks[i].temp_packets.size();
+ }
+ for (uint32_t i = 0; i < time_tracks.size(); i++) {
+ time_tracks[i].validated_key_index = time_tracks[i].key_index;
+ time_tracks[i].validated_packet_count = time_tracks[i].packets.size();
+ }
+
+ // Accept this frame as the frame being processed (as long as it exists)
+ if (best_frame != FRAME_MAX) {
+ current_frame = best_frame;
+ print_animc("\tValidated, New Current Frame: " + itos(current_frame));
+ }
+ }
+
+ if (rollback || best_frame == FRAME_MAX) {
+ // Commit the page if had to rollback or if no track was found
+ print_animc("\tCommiting page..");
+
+ // The end frame for the page depends entirely on whether its valid or
+ // no more keys were found.
+ // If not valid, then the end frame is the current frame (as this means the current frame is being rolled back
+ // If valid, then the end frame is the next invalid one (in case more frames exist), or the current frame in case no more frames exist.
+ uint32_t page_end_frame = (rollback || best_frame == FRAME_MAX) ? current_frame : best_invalid_frame;
+
+ print_animc("\tEnd Frame: " + itos(page_end_frame) + ", " + rtos(page_end_frame * frame_len) + "s");
+
+ // Add finalizer frames and commit pending tracks
+ uint32_t finalizer_local_frame = page_end_frame - base_page_frame;
+
+ uint32_t total_page_size = 0;
+
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ if (data_tracks[i].temp_packets.size() == 0 || (data_tracks[i].temp_packets[data_tracks[i].temp_packets.size() - 1].frame) < finalizer_local_frame) {
+ // Add finalizer frame if it makes sense
+ Vector3i values = _compress_key(tracks_to_compress[i], track_bounds[i], -1, page_end_frame * frame_len);
+
+ bool first_key = data_tracks[i].insert_key(finalizer_local_frame, values);
+ if (first_key) {
+ AnimationCompressionTimeState::Packet p;
+ p.count = 1;
+ p.frame = finalizer_local_frame;
+ p.offset = data_tracks[i].data.size();
+ time_tracks[i].packets.push_back(p);
+ } else {
+ ERR_FAIL_COND(time_tracks[i].packets.size() == 0);
+ time_tracks[i].packets[time_tracks[i].packets.size() - 1].count++;
+ }
+ }
+
+ data_tracks[i].commit_temp_packets();
+ total_page_size += data_tracks[i].data.size();
+ total_page_size += time_tracks[i].packets.size() * 4;
+ total_page_size += track_header_size;
+
+ print_animc("\tTrack " + itos(i) + " time packets: " + itos(time_tracks[i].packets.size()) + " Packet data: " + itos(data_tracks[i].data.size()));
+ }
+
+ print_animc("\tTotal page Size: " + itos(total_page_size) + "/" + itos(p_page_size));
+
+ // Create Page
+ Vector<uint8_t> page_data;
+ page_data.resize(total_page_size);
+ {
+ uint8_t *page_ptr = page_data.ptrw();
+ uint32_t base_offset = data_tracks.size() * track_header_size;
+
+ for (uint32_t i = 0; i < data_tracks.size(); i++) {
+ encode_uint32(base_offset, page_ptr + (track_header_size * i + 0));
+ uint16_t *key_time_ptr = (uint16_t *)(page_ptr + base_offset);
+ for (uint32_t j = 0; j < time_tracks[i].packets.size(); j++) {
+ key_time_ptr[j * 2 + 0] = uint16_t(time_tracks[i].packets[j].frame);
+ uint16_t ptr = time_tracks[i].packets[j].offset / 4;
+ ptr |= (time_tracks[i].packets[j].count - 1) << 12;
+ key_time_ptr[j * 2 + 1] = ptr;
+ base_offset += 4;
+ }
+ encode_uint32(time_tracks[i].packets.size(), page_ptr + (track_header_size * i + 4));
+ encode_uint32(base_offset, page_ptr + (track_header_size * i + 8));
+ memcpy(page_ptr + base_offset, data_tracks[i].data.ptr(), data_tracks[i].data.size());
+ base_offset += data_tracks[i].data.size();
+
+ //reset track
+ data_tracks[i].data.clear();
+ data_tracks[i].temp_packets.clear();
+ data_tracks[i].validated_packet_count = -1;
+
+ time_tracks[i].needs_start_frame = true; //Not required the first time, but from now on it is.
+ time_tracks[i].packets.clear();
+ time_tracks[i].validated_key_index = -1;
+ time_tracks[i].validated_packet_count = 0;
+ }
+ }
+
+ Compression::Page page;
+ page.data = page_data;
+ page.time_offset = base_page_frame * frame_len;
+ compression.pages.push_back(page);
+
+ if (!rollback && best_invalid_frame == FRAME_MAX) {
+ break; // No more pages to add.
+ }
+
+ current_frame = page_end_frame;
+ base_page_frame = page_end_frame;
+
+ continue; // Start over
+ }
+ }
+
+ // A key was found for the current frame and all is ok
+
+ uint32_t comp_track = best_frame_track;
+ Vector3i values;
+
+ if (start_frame) {
+ // Interpolate
+ values = _compress_key(tracks_to_compress[comp_track], track_bounds[comp_track], -1, base_page_frame * frame_len);
+ } else {
+ uint32_t key = time_tracks[comp_track].key_index;
+ values = _compress_key(tracks_to_compress[comp_track], track_bounds[comp_track], key);
+ time_tracks[comp_track].key_index++; //goto next key (but could be rolled back if beyond page size).
+ }
+
+ bool first_key = data_tracks[comp_track].insert_key(best_frame - base_page_frame, values);
+ if (first_key) {
+ AnimationCompressionTimeState::Packet p;
+ p.count = 1;
+ p.frame = best_frame - base_page_frame;
+ p.offset = data_tracks[comp_track].data.size();
+ time_tracks[comp_track].packets.push_back(p);
+ } else {
+ ERR_CONTINUE(time_tracks[comp_track].packets.size() == 0);
+ time_tracks[comp_track].packets[time_tracks[comp_track].packets.size() - 1].count++;
+ }
+ }
+
+ compression.bounds = track_bounds;
+ compression.fps = p_fps;
+ compression.enabled = true;
+
+ for (uint32_t i = 0; i < tracks_to_compress.size(); i++) {
+ Track *t = tracks[tracks_to_compress[i]];
+ t->interpolation = INTERPOLATION_LINEAR; //only linear supported
+ switch (t->type) {
+ case TYPE_POSITION_3D: {
+ PositionTrack *tt = static_cast<PositionTrack *>(t);
+ tt->positions.clear();
+ tt->compressed_track = i;
+ } break;
+ case TYPE_ROTATION_3D: {
+ RotationTrack *rt = static_cast<RotationTrack *>(t);
+ rt->rotations.clear();
+ rt->compressed_track = i;
+ } break;
+ case TYPE_SCALE_3D: {
+ ScaleTrack *st = static_cast<ScaleTrack *>(t);
+ st->scales.clear();
+ st->compressed_track = i;
+ print_line("Scale Bounds " + itos(i) + ": " + track_bounds[i]);
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ BlendShapeTrack *bst = static_cast<BlendShapeTrack *>(t);
+ bst->blend_shapes.clear();
+ bst->compressed_track = i;
+ } break;
+ default: {
+ }
+ }
+ }
+#if 1
+ uint32_t orig_size = 0;
+ for (int i = 0; i < get_track_count(); i++) {
+ switch (track_get_type(i)) {
+ case TYPE_SCALE_3D:
+ case TYPE_POSITION_3D: {
+ orig_size += sizeof(TKey<Vector3>) * track_get_key_count(i);
+ } break;
+ case TYPE_ROTATION_3D: {
+ orig_size += sizeof(TKey<Quaternion>) * track_get_key_count(i);
+ } break;
+ case TYPE_BLEND_SHAPE: {
+ orig_size += sizeof(TKey<float>) * track_get_key_count(i);
+ } break;
+ default: {
+ }
+ }
+ }
+
+ uint32_t new_size = 0;
+ for (uint32_t i = 0; i < compression.pages.size(); i++) {
+ new_size += compression.pages[i].data.size();
+ }
+
+ print_line("Original size: " + itos(orig_size) + " - Compressed size: " + itos(new_size) + " " + String::num(float(new_size) / float(orig_size) * 100, 2) + "% pages: " + itos(compression.pages.size()));
+#endif
+}
+
+bool Animation::_rotation_interpolate_compressed(uint32_t p_compressed_track, double p_time, Quaternion &r_ret) const {
+ Vector3i current;
+ Vector3i next;
+ double time_current;
+ double time_next;
+
+ if (!_fetch_compressed<3>(p_compressed_track, p_time, current, time_current, next, time_next)) {
+ return false; //some sort of problem
+ }
+
+ if (time_current >= p_time || time_current == time_next) {
+ r_ret = _uncompress_quaternion(current);
+ } else if (p_time >= time_next) {
+ r_ret = _uncompress_quaternion(next);
+ } else {
+ double c = (p_time - time_current) / (time_next - time_current);
+ Quaternion from = _uncompress_quaternion(current);
+ Quaternion to = _uncompress_quaternion(next);
+ r_ret = from.slerp(to, c);
+ }
+
+ return true;
+}
+
+bool Animation::_pos_scale_interpolate_compressed(uint32_t p_compressed_track, double p_time, Vector3 &r_ret) const {
+ Vector3i current;
+ Vector3i next;
+ double time_current;
+ double time_next;
+
+ if (!_fetch_compressed<3>(p_compressed_track, p_time, current, time_current, next, time_next)) {
+ return false; //some sort of problem
+ }
+
+ if (time_current >= p_time || time_current == time_next) {
+ r_ret = _uncompress_pos_scale(p_compressed_track, current);
+ } else if (p_time >= time_next) {
+ r_ret = _uncompress_pos_scale(p_compressed_track, next);
+ } else {
+ double c = (p_time - time_current) / (time_next - time_current);
+ Vector3 from = _uncompress_pos_scale(p_compressed_track, current);
+ Vector3 to = _uncompress_pos_scale(p_compressed_track, next);
+ r_ret = from.lerp(to, c);
+ }
+
+ return true;
+}
+bool Animation::_blend_shape_interpolate_compressed(uint32_t p_compressed_track, double p_time, float &r_ret) const {
+ Vector3i current;
+ Vector3i next;
+ double time_current;
+ double time_next;
+
+ if (!_fetch_compressed<1>(p_compressed_track, p_time, current, time_current, next, time_next)) {
+ return false; //some sort of problem
+ }
+
+ if (time_current >= p_time || time_current == time_next) {
+ r_ret = _uncompress_blend_shape(current);
+ } else if (p_time >= time_next) {
+ r_ret = _uncompress_blend_shape(next);
+ } else {
+ float c = (p_time - time_current) / (time_next - time_current);
+ float from = _uncompress_blend_shape(current);
+ float to = _uncompress_blend_shape(next);
+ r_ret = Math::lerp(from, to, c);
+ }
+
+ return true;
+}
+
+template <uint32_t COMPONENTS>
+bool Animation::_fetch_compressed(uint32_t p_compressed_track, double p_time, Vector3i &r_current_value, double &r_current_time, Vector3i &r_next_value, double &r_next_time, uint32_t *key_index) const {
+ ERR_FAIL_COND_V(!compression.enabled, false);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_compressed_track, compression.bounds.size(), false);
+ p_time = CLAMP(p_time, 0, length);
+ if (key_index) {
+ *key_index = 0;
+ }
+
+ double frame_to_sec = 1.0 / double(compression.fps);
+
+ int32_t page_index = -1;
+ for (uint32_t i = 0; i < compression.pages.size(); i++) {
+ if (compression.pages[i].time_offset > p_time) {
+ break;
+ }
+ page_index = i;
+ }
+
+ ERR_FAIL_COND_V(page_index == -1, false); //should not happen
+
+ double page_base_time = compression.pages[page_index].time_offset;
+ const uint8_t *page_data = compression.pages[page_index].data.ptr();
+#ifndef _MSC_VER
+#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported
+#endif
+ const uint32_t *indices = (const uint32_t *)page_data;
+ const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]];
+ uint32_t time_key_count = indices[p_compressed_track * 3 + 1];
+
+ int32_t packet_idx = 0;
+ double packet_time = double(time_keys[0]) * frame_to_sec + page_base_time;
+ uint32_t base_frame = time_keys[0];
+
+ for (uint32_t i = 1; i < time_key_count; i++) {
+ uint32_t f = time_keys[i * 2 + 0];
+ double frame_time = double(f) * frame_to_sec + page_base_time;
+
+ if (frame_time > p_time) {
+ break;
+ }
+
+ if (key_index) {
+ (*key_index) += (time_keys[(i - 1) * 2 + 1] >> 12) + 1;
+ }
+
+ packet_idx = i;
+ packet_time = frame_time;
+ base_frame = f;
+ }
+
+ const uint8_t *data_keys_base = (const uint8_t *)&page_data[indices[p_compressed_track * 3 + 2]];
+
+ uint16_t time_key_data = time_keys[packet_idx * 2 + 1];
+ uint32_t data_offset = (time_key_data & 0xFFF) * 4; // lower 12 bits
+ uint32_t data_count = (time_key_data >> 12) + 1;
+
+ const uint16_t *data_key = (const uint16_t *)(data_keys_base + data_offset);
+
+ uint16_t decode[COMPONENTS];
+ uint16_t decode_next[COMPONENTS];
+
+ for (uint32_t i = 0; i < COMPONENTS; i++) {
+ decode[i] = data_key[i];
+ decode_next[i] = data_key[i];
+ }
+
+ double next_time = packet_time;
+
+ if (p_time > packet_time) { // If its equal or less, then don't bother
+ if (data_count > 1) {
+ //decode forward
+ uint32_t bit_width[COMPONENTS];
+ for (uint32_t i = 0; i < COMPONENTS; i++) {
+ bit_width[i] = (data_key[COMPONENTS] >> (i * 4)) & 0xF;
+ }
+
+ uint32_t frame_bit_width = (data_key[COMPONENTS] >> 12) + 1;
+
+ AnimationCompressionBufferBitsRead buffer;
+
+ buffer.src_data = (const uint8_t *)&data_key[COMPONENTS + 1];
+
+ for (uint32_t i = 1; i < data_count; i++) {
+ uint32_t frame_delta = buffer.read(frame_bit_width);
+ base_frame += frame_delta;
+
+ for (uint32_t j = 0; j < COMPONENTS; j++) {
+ if (bit_width[j] == 0) {
+ continue; // do none
+ }
+ uint32_t valueu = buffer.read(bit_width[j] + 1);
+ bool sign = valueu & (1 << bit_width[j]);
+ int16_t value = valueu & ((1 << bit_width[j]) - 1);
+ if (sign) {
+ value = -value - 1;
+ }
+
+ decode_next[j] += value;
+ }
+
+ next_time = double(base_frame) * frame_to_sec + page_base_time;
+ if (p_time < next_time) {
+ break;
+ }
+
+ packet_time = next_time;
+
+ for (uint32_t j = 0; j < COMPONENTS; j++) {
+ decode[j] = decode_next[j];
+ }
+
+ if (key_index) {
+ (*key_index)++;
+ }
+ }
+ }
+
+ if (p_time > next_time) { // > instead of >= because if its equal, then it will be properly interpolated anyway
+ // So, the last frame found still has a time that is less than the required frame,
+ // will have to interpolate with the first frame of the next timekey.
+
+ if ((uint32_t)packet_idx < time_key_count - 1) { // Sanity check but should not matter much, otherwise current next packet is last packet
+
+ uint16_t time_key_data_next = time_keys[(packet_idx + 1) * 2 + 1];
+ uint32_t data_offset_next = (time_key_data_next & 0xFFF) * 4; // Lower 12 bits
+
+ const uint16_t *data_key_next = (const uint16_t *)(data_keys_base + data_offset_next);
+ base_frame = time_keys[(packet_idx + 1) * 2 + 0];
+ next_time = double(base_frame) * frame_to_sec + page_base_time;
+ for (uint32_t i = 0; i < COMPONENTS; i++) {
+ decode_next[i] = data_key_next[i];
+ }
+ }
+ }
+ }
+
+ r_current_time = packet_time;
+ r_next_time = next_time;
+
+ for (uint32_t i = 0; i < COMPONENTS; i++) {
+ r_current_value[i] = decode[i];
+ r_next_value[i] = decode_next[i];
+ }
+
+ return true;
+}
+
+template <uint32_t COMPONENTS>
+void Animation::_get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, List<int> *r_indices) const {
+ ERR_FAIL_COND(!compression.enabled);
+ ERR_FAIL_UNSIGNED_INDEX(p_compressed_track, compression.bounds.size());
+
+ double frame_to_sec = 1.0 / double(compression.fps);
+ uint32_t key_index = 0;
+
+ for (uint32_t p = 0; p < compression.pages.size(); p++) {
+ if (compression.pages[p].time_offset >= p_time + p_delta) {
+ // Page beyond range
+ return;
+ }
+
+ // Page within range
+
+ uint32_t page_index = p;
+
+ double page_base_time = compression.pages[page_index].time_offset;
+ const uint8_t *page_data = compression.pages[page_index].data.ptr();
+#ifndef _MSC_VER
+#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported
+#endif
+ const uint32_t *indices = (const uint32_t *)page_data;
+ const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]];
+ uint32_t time_key_count = indices[p_compressed_track * 3 + 1];
+
+ for (uint32_t i = 0; i < time_key_count; i++) {
+ uint32_t f = time_keys[i * 2 + 0];
+ double frame_time = f * frame_to_sec + page_base_time;
+ if (frame_time >= p_time + p_delta) {
+ return;
+ } else if (frame_time >= p_time) {
+ r_indices->push_back(key_index);
+ }
+
+ key_index++;
+
+ const uint8_t *data_keys_base = (const uint8_t *)&page_data[indices[p_compressed_track * 3 + 2]];
+
+ uint16_t time_key_data = time_keys[i * 2 + 1];
+ uint32_t data_offset = (time_key_data & 0xFFF) * 4; // lower 12 bits
+ uint32_t data_count = (time_key_data >> 12) + 1;
+
+ const uint16_t *data_key = (const uint16_t *)(data_keys_base + data_offset);
+
+ if (data_count > 1) {
+ //decode forward
+ uint32_t bit_width[COMPONENTS];
+ for (uint32_t j = 0; j < COMPONENTS; j++) {
+ bit_width[j] = (data_key[COMPONENTS] >> (j * 4)) & 0xF;
+ }
+
+ uint32_t frame_bit_width = (data_key[COMPONENTS] >> 12) + 1;
+
+ AnimationCompressionBufferBitsRead buffer;
+
+ buffer.src_data = (const uint8_t *)&data_key[COMPONENTS + 1];
+
+ for (uint32_t j = 1; j < data_count; j++) {
+ uint32_t frame_delta = buffer.read(frame_bit_width);
+ f += frame_delta;
+
+ frame_time = f * frame_to_sec + page_base_time;
+ if (frame_time >= p_time + p_delta) {
+ return;
+ } else if (frame_time >= p_time) {
+ r_indices->push_back(key_index);
+ }
+
+ for (uint32_t k = 0; k < COMPONENTS; k++) {
+ if (bit_width[k] == 0) {
+ continue; // do none
+ }
+ buffer.read(bit_width[k] + 1); // skip
+ }
+
+ key_index++;
+ }
+ }
+ }
+ }
+}
+
+int Animation::_get_compressed_key_count(uint32_t p_compressed_track) const {
+ ERR_FAIL_COND_V(!compression.enabled, -1);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_compressed_track, compression.bounds.size(), -1);
+
+ int key_count = 0;
+
+ for (uint32_t i = 0; i < compression.pages.size(); i++) {
+ const uint8_t *page_data = compression.pages[i].data.ptr();
+#ifndef _MSC_VER
+#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported
+#endif
+ const uint32_t *indices = (const uint32_t *)page_data;
+ const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]];
+ uint32_t time_key_count = indices[p_compressed_track * 3 + 1];
+
+ for (uint32_t j = 0; j < time_key_count; j++) {
+ key_count += (time_keys[j * 2 + 1] >> 12) + 1;
+ }
+ }
+
+ return key_count;
+}
+
+Quaternion Animation::_uncompress_quaternion(const Vector3i &p_value) const {
+ Vector3 axis = Vector3::octahedron_decode(Vector2(float(p_value.x) / 65535.0, float(p_value.y) / 65535.0));
+ float angle = (float(p_value.z) / 65535.0) * 2.0 * Math_PI;
+ return Quaternion(axis, angle);
+}
+Vector3 Animation::_uncompress_pos_scale(uint32_t p_compressed_track, const Vector3i &p_value) const {
+ Vector3 pos_norm(float(p_value.x) / 65535.0, float(p_value.y) / 65535.0, float(p_value.z) / 65535.0);
+ return compression.bounds[p_compressed_track].position + pos_norm * compression.bounds[p_compressed_track].size;
+}
+float Animation::_uncompress_blend_shape(const Vector3i &p_value) const {
+ float bsn = float(p_value.x) / 65535.0;
+ return (bsn * 2.0 - 1.0) * float(Compression::BLEND_SHAPE_RANGE);
+}
+
+template <uint32_t COMPONENTS>
+bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_index, Vector3i &r_value, double &r_time) const {
+ ERR_FAIL_COND_V(!compression.enabled, false);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_compressed_track, compression.bounds.size(), false);
+
+ for (uint32_t i = 0; i < compression.pages.size(); i++) {
+ const uint8_t *page_data = compression.pages[i].data.ptr();
+#ifndef _MSC_VER
+#warning Little endian assumed. No major big endian hardware exists any longer, but in case it does it will need to be supported
+#endif
+ const uint32_t *indices = (const uint32_t *)page_data;
+ const uint16_t *time_keys = (const uint16_t *)&page_data[indices[p_compressed_track * 3 + 0]];
+ uint32_t time_key_count = indices[p_compressed_track * 3 + 1];
+ const uint8_t *data_keys_base = (const uint8_t *)&page_data[indices[p_compressed_track * 3 + 2]];
+
+ for (uint32_t j = 0; j < time_key_count; j++) {
+ uint32_t subkeys = (time_keys[j * 2 + 1] >> 12) + 1;
+ if ((uint32_t)p_index < subkeys) {
+ uint16_t data_offset = (time_keys[j * 2 + 1] & 0xFFF) * 4;
+
+ const uint16_t *data_key = (const uint16_t *)(data_keys_base + data_offset);
+
+ uint16_t frame = time_keys[j * 2 + 0];
+ uint16_t decode[COMPONENTS];
+
+ for (uint32_t k = 0; k < COMPONENTS; k++) {
+ decode[k] = data_key[k];
+ }
+
+ if (p_index > 0) {
+ uint32_t bit_width[COMPONENTS];
+ for (uint32_t k = 0; k < COMPONENTS; k++) {
+ bit_width[k] = (data_key[COMPONENTS] >> (k * 4)) & 0xF;
+ }
+ uint32_t frame_bit_width = (data_key[COMPONENTS] >> 12) + 1;
+
+ AnimationCompressionBufferBitsRead buffer;
+ buffer.src_data = (const uint8_t *)&data_key[COMPONENTS + 1];
+
+ for (int k = 0; k < p_index; k++) {
+ uint32_t frame_delta = buffer.read(frame_bit_width);
+ frame += frame_delta;
+ for (uint32_t l = 0; l < COMPONENTS; l++) {
+ if (bit_width[l] == 0) {
+ continue; // do none
+ }
+ uint32_t valueu = buffer.read(bit_width[l] + 1);
+ bool sign = valueu & (1 << bit_width[l]);
+ int16_t value = valueu & ((1 << bit_width[l]) - 1);
+ if (sign) {
+ value = -value - 1;
+ }
+
+ decode[l] += value;
+ }
+ }
+ }
+
+ r_time = compression.pages[i].time_offset + double(frame) / double(compression.fps);
+ for (uint32_t l = 0; l < COMPONENTS; l++) {
+ r_value[l] = decode[l];
+ }
+
+ return true;
+
+ } else {
+ p_index -= subkeys;
+ }
+ }
+ }
+
+ return false;
+}
+
Animation::Animation() {}
Animation::~Animation() {
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 4ee0741d87..ee07fb19d3 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -32,6 +32,7 @@
#define ANIMATION_H
#include "core/io/resource.h"
+#include "core/templates/local_vector.h"
#define ANIM_MIN_LENGTH 0.001
@@ -98,7 +99,7 @@ private:
struct PositionTrack : public Track {
Vector<TKey<Vector3>> positions;
-
+ int32_t compressed_track = -1;
PositionTrack() { type = TYPE_POSITION_3D; }
};
@@ -106,7 +107,7 @@ private:
struct RotationTrack : public Track {
Vector<TKey<Quaternion>> rotations;
-
+ int32_t compressed_track = -1;
RotationTrack() { type = TYPE_ROTATION_3D; }
};
@@ -114,6 +115,7 @@ private:
struct ScaleTrack : public Track {
Vector<TKey<Vector3>> scales;
+ int32_t compressed_track = -1;
ScaleTrack() { type = TYPE_SCALE_3D; }
};
@@ -121,6 +123,7 @@ private:
struct BlendShapeTrack : public Track {
Vector<TKey<float>> blend_shapes;
+ int32_t compressed_track = -1;
BlendShapeTrack() { type = TYPE_BLEND_SHAPE; }
};
@@ -230,6 +233,89 @@ private:
real_t step = 0.1;
bool loop = false;
+ /* Animation compression page format (version 1):
+ *
+ * Animation uses bitwidth based compression separated into small pages. The intention is that pages fit easily in the cache, so decoding is cache efficient.
+ * The page-based nature also makes future animation streaming from disk possible.
+ *
+ * Actual format:
+ *
+ * num_compressed_tracks = bounds.size()
+ * header : (x num_compressed_tracks)
+ * -------
+ * timeline_keys_offset : uint32_t - offset to time keys
+ * timeline_size : uint32_t - amount of time keys
+ * data_keys_offset : uint32_t offset to key data
+ *
+ * time key (uint32_t):
+ * ------------------
+ * frame : bits 0-15 - time offset of key, computed as: page.time_offset + frame * (1.0/fps)
+ * data_key_offset : bits 16-27 - offset to key data, computed as: data_keys_offset * 4 + data_key_offset
+ * data_key_count : bits 28-31 - amount of data keys pointed to, computed as: data_key_count+1 (max 16)
+ *
+ * data key:
+ * ---------
+ * X / Blend Shape : uint16_t - X coordinate of XYZ vector key, or Blend Shape value. If Blend shape, Y and Z are not present and can be ignored.
+ * Y : uint16_t
+ * Z : uint16_t
+ * If data_key_count+1 > 1 (if more than 1 key is stored):
+ * data_bitwidth : uint16_t - This is only present if data_key_count > 1. Contains delta bitwidth information.
+ * X / Blend Shape delta bitwidth: bits 0-3 -
+ * if 0, nothing is present for X (use the first key-value for subsequent keys),
+ * else assume the number of bits present for each element (+ 1 for sign). Assumed always 16 bits, delta max signed 15 bits, with underflow and overflow supported.
+ * Y delta bitwidth : bits 4-7
+ * Z delta bitwidth : bits 8-11
+ * FRAME delta bitwidth : 12-15 bits - always present (obviously), actual bitwidth is FRAME+1
+ * Data key is 4 bytes long for Blend Shapes, 8 bytes long for pos/rot/scale.
+ *
+ * delta keys:
+ * -----------
+ * Compressed format is packed in the following format after the data key, containing delta keys one after the next in a tightly bit packed fashion.
+ * FRAME bits -> X / Blend Shape Bits (if bitwidth > 0) -> Y Bits (if not Blend Shape and Y Bitwidth > 0) -> Z Bits (if not Blend Shape and Z Bitwidth > 0)
+ *
+ * data key format:
+ * ----------------
+ * Decoding keys means starting from the base key and going key by key applying deltas until the proper position is reached needed for interpolation.
+ * Resulting values are uint32_t
+ * data for X / Blend Shape, Y and Z must be normalized first: unorm = float(data) / 65535.0
+ * **Blend Shape**: (unorm * 2.0 - 1.0) * Compression::BLEND_SHAPE_RANGE
+ * **Pos/Scale**: unorm_vec3 * bounds[track].size + bounds[track].position
+ * **Rotation**: Quaternion(Vector3::octahedron_decode(unorm_vec3.xy),unorm_vec3.z * Math_PI * 2.0)
+ * **Frame**: page.time_offset + frame * (1.0/fps)
+ */
+
+ struct Compression {
+ enum {
+ MAX_DATA_TRACK_SIZE = 16384,
+ BLEND_SHAPE_RANGE = 8, // - 8.0 to 8.0
+ FORMAT_VERSION = 1
+ };
+ struct Page {
+ Vector<uint8_t> data;
+ double time_offset;
+ };
+
+ uint32_t fps = 120;
+ LocalVector<Page> pages;
+ LocalVector<AABB> bounds; //used by position and scale tracks (which contain index to track and index to bounds).
+ bool enabled = false;
+ } compression;
+
+ Vector3i _compress_key(uint32_t p_track, const AABB &p_bounds, int32_t p_key = -1, float p_time = 0.0);
+ bool _rotation_interpolate_compressed(uint32_t p_compressed_track, double p_time, Quaternion &r_ret) const;
+ bool _pos_scale_interpolate_compressed(uint32_t p_compressed_track, double p_time, Vector3 &r_ret) const;
+ bool _blend_shape_interpolate_compressed(uint32_t p_compressed_track, double p_time, float &r_ret) const;
+ template <uint32_t COMPONENTS>
+ bool _fetch_compressed(uint32_t p_compressed_track, double p_time, Vector3i &r_current_value, double &r_current_time, Vector3i &r_next_value, double &r_next_time, uint32_t *key_index = nullptr) const;
+ template <uint32_t COMPONENTS>
+ bool _fetch_compressed_by_index(uint32_t p_compressed_track, int p_index, Vector3i &r_value, double &r_time) const;
+ int _get_compressed_key_count(uint32_t p_compressed_track) const;
+ template <uint32_t COMPONENTS>
+ void _get_compressed_key_indices_in_range(uint32_t p_compressed_track, double p_time, double p_delta, List<int> *r_indices) const;
+ _FORCE_INLINE_ Quaternion _uncompress_quaternion(const Vector3i &p_value) const;
+ _FORCE_INLINE_ Vector3 _uncompress_pos_scale(uint32_t p_compressed_track, const Vector3i &p_value) const;
+ _FORCE_INLINE_ float _uncompress_blend_shape(const Vector3i &p_value) const;
+
// bind helpers
private:
Vector<int> _value_track_get_key_indices(int p_track, double p_time, double p_delta) const {
@@ -281,8 +367,7 @@ public:
void track_set_path(int p_track, const NodePath &p_path);
NodePath track_get_path(int p_track) const;
- int find_track(const NodePath &p_path) const;
- // transform
+ int find_track(const NodePath &p_path, const TrackType p_type) const;
void track_move_up(int p_track);
void track_move_down(int p_track);
@@ -306,6 +391,7 @@ public:
Variant track_get_key_value(int p_track, int p_key_idx) const;
double track_get_key_time(int p_track, int p_key_idx) const;
real_t track_get_key_transition(int p_track, int p_key_idx) const;
+ bool track_is_compressed(int p_track) const;
int position_track_insert_key(int p_track, double p_time, const Vector3 &p_position);
Error position_track_get_key(int p_track, int p_key, Vector3 *r_position) const;
@@ -376,6 +462,7 @@ public:
void clear();
void optimize(real_t p_allowed_linear_err = 0.05, real_t p_allowed_angular_err = 0.01, real_t p_max_optimizable_angle = Math_PI * 0.125);
+ void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests
Animation();
~Animation();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 9fdfd493c1..ed093d7ea3 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -1030,7 +1030,6 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {
dynamic_font_data.instantiate();
dynamic_font_data->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size);
dynamic_font->add_data(dynamic_font_data);
- dynamic_font->set_base_size(default_font_size);
default_font = dynamic_font;
}
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 04e2b0dc70..819ae95715 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -1072,10 +1072,6 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_data"), &Font::clear_data);
ClassDB::bind_method(D_METHOD("remove_data", "idx"), &Font::remove_data);
- ClassDB::bind_method(D_METHOD("set_base_size", "size"), &Font::set_base_size);
- ClassDB::bind_method(D_METHOD("get_base_size"), &Font::get_base_size);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "base_size"), "set_base_size", "get_base_size");
-
ClassDB::bind_method(D_METHOD("set_variation_coordinates", "variation_coordinates"), &Font::set_variation_coordinates);
ClassDB::bind_method(D_METHOD("get_variation_coordinates"), &Font::get_variation_coordinates);
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "variation_coordinates"), "set_variation_coordinates", "get_variation_coordinates");
@@ -1087,20 +1083,20 @@ void Font::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
- ClassDB::bind_method(D_METHOD("get_height", "size"), &Font::get_height, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_ascent", "size"), &Font::get_ascent, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_descent", "size"), &Font::get_descent, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_underline_position", "size"), &Font::get_underline_position, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_underline_thickness", "size"), &Font::get_underline_thickness, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_height", "size"), &Font::get_height, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_ascent", "size"), &Font::get_ascent, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_descent", "size"), &Font::get_descent, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_underline_position", "size"), &Font::get_underline_position, DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("get_underline_thickness", "size"), &Font::get_underline_thickness, DEFVAL(DEFAULT_FONT_SIZE));
- ClassDB::bind_method(D_METHOD("get_string_size", "text", "size", "align", "width", "flags"), &Font::get_string_size, DEFVAL(-1), DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "width", "size", "flags"), &Font::get_multiline_string_size, DEFVAL(-1), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("get_string_size", "text", "size", "align", "width", "flags"), &Font::get_string_size, DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "width", "size", "flags"), &Font::get_multiline_string_size, DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "align", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "align", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_multiline_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "align", "width", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
+ ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "align", "width", "max_lines", "size", "modulate", "outline_size", "outline_modulate", "flags"), &Font::draw_multiline_string, DEFVAL(HALIGN_LEFT), DEFVAL(-1), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("get_char_size", "char", "next", "size"), &Font::get_char_size, DEFVAL(0), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "next", "size", "modulate", "outline_size", "outline_modulate"), &Font::draw_char, DEFVAL(0), DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)));
+ ClassDB::bind_method(D_METHOD("get_char_size", "char", "next", "size"), &Font::get_char_size, DEFVAL(0), DEFVAL(DEFAULT_FONT_SIZE));
+ ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "next", "size", "modulate", "outline_size", "outline_modulate"), &Font::draw_char, DEFVAL(0), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(1, 1, 1, 0)));
ClassDB::bind_method(D_METHOD("has_char", "char"), &Font::has_char);
ClassDB::bind_method(D_METHOD("get_supported_chars"), &Font::get_supported_chars);
@@ -1195,7 +1191,6 @@ void Font::reset_state() {
data.clear();
rids.clear();
- base_size = 16;
variation_coordinates.clear();
spacing_bottom = 0;
spacing_top = 0;
@@ -1308,14 +1303,6 @@ void Font::remove_data(int p_idx) {
notify_property_list_changed();
}
-void Font::set_base_size(int p_size) {
- base_size = p_size;
-}
-
-int Font::get_base_size() const {
- return base_size;
-}
-
void Font::set_variation_coordinates(const Dictionary &p_variation_coordinates) {
_data_changed();
variation_coordinates = p_variation_coordinates;
@@ -1355,51 +1342,46 @@ int Font::get_spacing(TextServer::SpacingType p_spacing) const {
}
real_t Font::get_height(int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
real_t ret = 0.f;
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
- ret = MAX(ret, TS->font_get_ascent(rids[i], size) + TS->font_get_descent(rids[i], size));
+ ret = MAX(ret, TS->font_get_ascent(rids[i], p_size) + TS->font_get_descent(rids[i], p_size));
}
return ret + spacing_bottom + spacing_top;
}
real_t Font::get_ascent(int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
real_t ret = 0.f;
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
- ret = MAX(ret, TS->font_get_ascent(rids[i], size));
+ ret = MAX(ret, TS->font_get_ascent(rids[i], p_size));
}
return ret + spacing_top;
}
real_t Font::get_descent(int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
real_t ret = 0.f;
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
- ret = MAX(ret, TS->font_get_descent(rids[i], size));
+ ret = MAX(ret, TS->font_get_descent(rids[i], p_size));
}
return ret + spacing_bottom;
}
real_t Font::get_underline_position(int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
real_t ret = 0.f;
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
- ret = MAX(ret, TS->font_get_underline_position(rids[i], size));
+ ret = MAX(ret, TS->font_get_underline_position(rids[i], p_size));
}
return ret + spacing_top;
}
real_t Font::get_underline_thickness(int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
real_t ret = 0.f;
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
- ret = MAX(ret, TS->font_get_underline_thickness(rids[i], size));
+ ret = MAX(ret, TS->font_get_underline_thickness(rids[i], p_size));
}
return ret;
}
@@ -1407,8 +1389,6 @@ real_t Font::get_underline_thickness(int p_size) const {
Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, real_t p_width, uint16_t p_flags) const {
ERR_FAIL_COND_V(data.is_empty(), Size2());
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
}
@@ -1418,14 +1398,14 @@ Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, re
hash = hash_djb2_one_64(hash_djb2_one_float(p_width), hash);
hash = hash_djb2_one_64(p_flags, hash);
}
- hash = hash_djb2_one_64(size, hash);
+ hash = hash_djb2_one_64(p_size, hash);
Ref<TextLine> buffer;
if (cache.has(hash)) {
buffer = cache.get(hash);
} else {
buffer.instantiate();
- buffer->add_string(p_text, Ref<Font>(this), size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ buffer->add_string(p_text, Ref<Font>(this), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
cache.insert(hash, buffer);
}
return buffer->get_size();
@@ -1434,8 +1414,6 @@ Size2 Font::get_string_size(const String &p_text, int p_size, HAlign p_align, re
Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int p_size, uint16_t p_flags) const {
ERR_FAIL_COND_V(data.is_empty(), Size2());
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
}
@@ -1443,14 +1421,14 @@ Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int
uint64_t hash = p_text.hash64();
uint64_t wrp_hash = hash_djb2_one_64(hash_djb2_one_float(p_width), hash);
wrp_hash = hash_djb2_one_64(p_flags, wrp_hash);
- wrp_hash = hash_djb2_one_64(size, wrp_hash);
+ wrp_hash = hash_djb2_one_64(p_size, wrp_hash);
Ref<TextParagraph> lines_buffer;
if (cache_wrap.has(wrp_hash)) {
lines_buffer = cache_wrap.get(wrp_hash);
} else {
lines_buffer.instantiate();
- lines_buffer->add_string(p_text, Ref<Font>(this), size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ lines_buffer->add_string(p_text, Ref<Font>(this), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
lines_buffer->set_width(p_width);
lines_buffer->set_flags(p_flags);
cache_wrap.insert(wrp_hash, lines_buffer);
@@ -1473,8 +1451,6 @@ Size2 Font::get_multiline_string_size(const String &p_text, real_t p_width, int
void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, real_t p_width, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint16_t p_flags) const {
ERR_FAIL_COND(data.is_empty());
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
}
@@ -1484,14 +1460,14 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t
hash = hash_djb2_one_64(hash_djb2_one_float(p_width), hash);
hash = hash_djb2_one_64(p_flags, hash);
}
- hash = hash_djb2_one_64(size, hash);
+ hash = hash_djb2_one_64(p_size, hash);
Ref<TextLine> buffer;
if (cache.has(hash)) {
buffer = cache.get(hash);
} else {
buffer.instantiate();
- buffer->add_string(p_text, Ref<Font>(this), size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ buffer->add_string(p_text, Ref<Font>(this), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
cache.insert(hash, buffer);
}
@@ -1515,8 +1491,6 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t
void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align, float p_width, int p_max_lines, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate, uint16_t p_flags) const {
ERR_FAIL_COND(data.is_empty());
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
}
@@ -1524,14 +1498,14 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S
uint64_t hash = p_text.hash64();
uint64_t wrp_hash = hash_djb2_one_64(hash_djb2_one_float(p_width), hash);
wrp_hash = hash_djb2_one_64(p_flags, wrp_hash);
- wrp_hash = hash_djb2_one_64(size, wrp_hash);
+ wrp_hash = hash_djb2_one_64(p_size, wrp_hash);
Ref<TextParagraph> lines_buffer;
if (cache_wrap.has(wrp_hash)) {
lines_buffer = cache_wrap.get(wrp_hash);
} else {
lines_buffer.instantiate();
- lines_buffer->add_string(p_text, Ref<Font>(this), size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
+ lines_buffer->add_string(p_text, Ref<Font>(this), p_size, Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
lines_buffer->set_width(p_width);
lines_buffer->set_flags(p_flags);
cache_wrap.insert(wrp_hash, lines_buffer);
@@ -1573,16 +1547,14 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S
}
Size2 Font::get_char_size(char32_t p_char, char32_t p_next, int p_size) const {
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
if (data[i]->has_char(p_char)) {
- int32_t glyph_a = TS->font_get_glyph_index(rids[i], size, p_char, 0);
- Size2 ret = Size2(TS->font_get_glyph_advance(rids[i], size, glyph_a).x, TS->font_get_ascent(rids[i], size) + TS->font_get_descent(rids[i], size));
+ int32_t glyph_a = TS->font_get_glyph_index(rids[i], p_size, p_char, 0);
+ Size2 ret = Size2(TS->font_get_glyph_advance(rids[i], p_size, glyph_a).x, TS->font_get_ascent(rids[i], p_size) + TS->font_get_descent(rids[i], p_size));
if ((p_next != 0) && data[i]->has_char(p_next)) {
- int32_t glyph_b = TS->font_get_glyph_index(rids[i], size, p_next, 0);
- ret.x -= TS->font_get_kerning(rids[i], size, Vector2i(glyph_a, glyph_b)).x;
+ int32_t glyph_b = TS->font_get_glyph_index(rids[i], p_size, p_next, 0);
+ ret.x -= TS->font_get_kerning(rids[i], p_size, Vector2i(glyph_a, glyph_b)).x;
}
return ret;
}
@@ -1591,22 +1563,20 @@ Size2 Font::get_char_size(char32_t p_char, char32_t p_next, int p_size) const {
}
real_t Font::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, int p_size, const Color &p_modulate, int p_outline_size, const Color &p_outline_modulate) const {
- int size = (p_size <= 0) ? base_size : p_size;
-
for (int i = 0; i < data.size(); i++) {
_ensure_rid(i);
if (data[i]->has_char(p_char)) {
- int32_t glyph_a = TS->font_get_glyph_index(rids[i], size, p_char, 0);
- real_t ret = TS->font_get_glyph_advance(rids[i], size, glyph_a).x;
+ int32_t glyph_a = TS->font_get_glyph_index(rids[i], p_size, p_char, 0);
+ real_t ret = TS->font_get_glyph_advance(rids[i], p_size, glyph_a).x;
if ((p_next != 0) && data[i]->has_char(p_next)) {
- int32_t glyph_b = TS->font_get_glyph_index(rids[i], size, p_next, 0);
- ret -= TS->font_get_kerning(rids[i], size, Vector2i(glyph_a, glyph_b)).x;
+ int32_t glyph_b = TS->font_get_glyph_index(rids[i], p_size, p_next, 0);
+ ret -= TS->font_get_kerning(rids[i], p_size, Vector2i(glyph_a, glyph_b)).x;
}
if (p_outline_size > 0 && p_outline_modulate.a != 0.0f) {
- TS->font_draw_glyph_outline(rids[i], p_canvas_item, size, p_outline_size, p_pos, glyph_a, p_outline_modulate);
+ TS->font_draw_glyph_outline(rids[i], p_canvas_item, p_size, p_outline_size, p_pos, glyph_a, p_outline_modulate);
}
- TS->font_draw_glyph(rids[i], p_canvas_item, size, p_pos, glyph_a, p_modulate);
+ TS->font_draw_glyph(rids[i], p_canvas_item, p_size, p_pos, glyph_a, p_modulate);
return ret;
}
}
diff --git a/scene/resources/font.h b/scene/resources/font.h
index e65fdb0751..e1f1f6d742 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -219,7 +219,6 @@ class Font : public Resource {
mutable Vector<RID> rids;
// Font config.
- int base_size = 16;
Dictionary variation_coordinates;
int spacing_bottom = 0;
int spacing_top = 0;
@@ -237,6 +236,8 @@ protected:
virtual void reset_state() override;
public:
+ static const int DEFAULT_FONT_SIZE = 16;
+
Dictionary get_feature_list() const;
// Font data.
@@ -249,9 +250,6 @@ public:
virtual void remove_data(int p_idx);
// Font configuration.
- virtual void set_base_size(int p_size);
- virtual int get_base_size() const;
-
virtual void set_variation_coordinates(const Dictionary &p_variation_coordinates);
virtual Dictionary get_variation_coordinates() const;
@@ -259,26 +257,26 @@ public:
virtual int get_spacing(TextServer::SpacingType p_spacing) const;
// Font metrics.
- virtual real_t get_height(int p_size = -1) const;
- virtual real_t get_ascent(int p_size = -1) const;
- virtual real_t get_descent(int p_size = -1) const;
- virtual real_t get_underline_position(int p_size = -1) const;
- virtual real_t get_underline_thickness(int p_size = -1) const;
+ virtual real_t get_height(int p_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t get_ascent(int p_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t get_descent(int p_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t get_underline_position(int p_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t get_underline_thickness(int p_size = DEFAULT_FONT_SIZE) const;
// Drawing string.
- virtual Size2 get_string_size(const String &p_text, int p_size = -1, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- virtual Size2 get_multiline_string_size(const String &p_text, real_t p_width = -1, int p_size = -1, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) const;
+ virtual Size2 get_string_size(const String &p_text, int p_size = DEFAULT_FONT_SIZE, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ virtual Size2 get_multiline_string_size(const String &p_text, real_t p_width = -1, int p_size = DEFAULT_FONT_SIZE, uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND) const;
- virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
- virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ virtual void draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
+ virtual void draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HAlign p_align = HALIGN_LEFT, real_t p_width = -1, int p_max_lines = -1, int p_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0), uint16_t p_flags = TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND) const;
// Helper functions.
virtual bool has_char(char32_t p_char) const;
virtual String get_supported_chars() const;
// Drawing char.
- virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0, int p_size = -1) const;
- virtual real_t draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, int p_size = -1, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
+ virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0, int p_size = DEFAULT_FONT_SIZE) const;
+ virtual real_t draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, int p_size = DEFAULT_FONT_SIZE, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, const Color &p_outline_modulate = Color(1, 1, 1, 0)) const;
Vector<RID> get_rids() const;
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 65cdc1e24e..99977a20f2 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -169,7 +169,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
const StringName *key2 = nullptr;
while ((key2 = font_size_map[*key].next(key2))) {
- list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2));
+ list.push_back(PropertyInfo(Variant::INT, String() + *key + "/font_sizes/" + *key2, PROPERTY_HINT_RANGE, "0,256,1,or_greater"));
}
}
@@ -1655,7 +1655,7 @@ void Theme::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_base_scale", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,or_greater"), "set_default_base_scale", "get_default_base_scale");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size"), "set_default_font_size", "get_default_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size", PROPERTY_HINT_RANGE, "0,256,1,or_greater"), "set_default_font_size", "get_default_font_size");
BIND_ENUM_CONSTANT(DATA_TYPE_COLOR);
BIND_ENUM_CONSTANT(DATA_TYPE_CONSTANT);
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index a6101530c8..3fb47e8f05 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -497,6 +497,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_NATIVE_ICON);
BIND_ENUM_CONSTANT(FEATURE_ORIENTATION);
BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS);
+ BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
diff --git a/servers/display_server.h b/servers/display_server.h
index 8af7946a1e..2595cf2eb8 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -114,6 +114,7 @@ public:
FEATURE_ORIENTATION,
FEATURE_SWAP_BUFFERS,
FEATURE_KEEP_SCREEN_ON,
+ FEATURE_CLIPBOARD_PRIMARY,
};
virtual bool has_feature(Feature p_feature) const = 0;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 987960069b..5bb8fea89a 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -1251,6 +1251,7 @@ void main() {
{ //directional light
+#ifndef SHADOWS_DISABLED
// Do shadow and lighting in two passes to reduce register pressure
uint shadow0 = 0;
uint shadow1 = 0;
@@ -1449,6 +1450,7 @@ void main() {
shadow1 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << ((i - 4) * 8);
}
}
+#endif // SHADOWS_DISABLED
for (uint i = 0; i < 8; i++) {
if (i >= scene_data.directional_light_count) {
@@ -1511,12 +1513,13 @@ void main() {
#endif
float shadow = 1.0;
-
+#ifndef SHADOWS_DISABLED
if (i < 4) {
shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+#endif
blur_shadow(shadow);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 72872c9c08..61559fe809 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -287,7 +287,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif //defined(LIGHT_CODE_USED)
}
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
// Interleaved Gradient Noise
// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
@@ -433,7 +433,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex
}
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
float get_omni_attenuation(float distance, float inv_range, float decay) {
float nd = distance * inv_range;
@@ -445,7 +445,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
}
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (omni_lights.data[idx].shadow_enabled) {
// there is a shadowmap
vec2 texel_size = scene_data.shadow_atlas_pixel_size;
@@ -730,7 +730,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
}
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
-#ifndef USE_NO_SHADOWS
+#ifndef SHADOWS_DISABLED
if (spot_lights.data[idx].shadow_enabled) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
@@ -806,7 +806,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
return shadow;
}
-#endif //USE_NO_SHADOWS
+#endif // SHADOWS_DISABLED
return 1.0;
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index a7886bb6b1..cf422962f0 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1139,7 +1139,7 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if (instance->scenario && instance->array_index >= 0) {
InstanceData &idata = instance->scenario->instance_data[instance->array_index];
- if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
} else {
idata.flags &= ~uint32_t(InstanceData::FLAG_CAST_SHADOWS);
@@ -1603,7 +1603,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
//always dirty when added
idata.flags |= InstanceData::FLAG_REFLECTION_PROBE_DIRTY;
}
- if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+ if (p_instance->cast_shadows != RS::SHADOW_CASTING_SETTING_OFF) {
idata.flags |= InstanceData::FLAG_CAST_SHADOWS;
}
if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {