diff options
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="""" /> - <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) { |