summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format95
-rw-r--r--.github/workflows/linux_builds.yml59
-rw-r--r--.github/workflows/static_checks.yml4
-rw-r--r--.gitignore3
-rw-r--r--core/config/project_settings.cpp7
-rw-r--r--core/config/project_settings.h1
-rw-r--r--core/input/input.cpp1
-rw-r--r--core/input/input.h1
-rw-r--r--core/io/compression.h2
-rw-r--r--core/io/image.cpp2
-rw-r--r--core/io/logger.h1
-rw-r--r--core/math/basis.cpp508
-rw-r--r--core/math/basis.h42
-rw-r--r--core/math/convex_hull.cpp2
-rw-r--r--core/math/geometry_2d.h2
-rw-r--r--core/math/geometry_3d.h2
-rw-r--r--core/math/quaternion.cpp13
-rw-r--r--core/math/quaternion.h3
-rw-r--r--core/math/vector3.h27
-rw-r--r--core/os/memory.h1
-rw-r--r--core/os/os.cpp9
-rw-r--r--core/string/ustring.cpp6
-rw-r--r--core/variant/binder_common.h1
-rw-r--r--core/variant/variant.cpp4
-rw-r--r--core/variant/variant_call.cpp14
-rw-r--r--core/variant/variant_construct.cpp3
-rw-r--r--core/variant/variant_internal.h6
-rw-r--r--doc/classes/Animation.xml15
-rw-r--r--doc/classes/Basis.xml28
-rw-r--r--doc/classes/CanvasItem.xml6
-rw-r--r--doc/classes/Control.xml2
-rw-r--r--doc/classes/DirectionalLight2D.xml2
-rw-r--r--doc/classes/DirectionalLight3D.xml12
-rw-r--r--doc/classes/DisplayServer.xml17
-rw-r--r--doc/classes/EditorImportPlugin.xml4
-rw-r--r--doc/classes/Font.xml25
-rw-r--r--doc/classes/Input.xml7
-rw-r--r--doc/classes/LineEdit.xml4
-rw-r--r--doc/classes/Node3D.xml32
-rw-r--r--doc/classes/OS.xml4
-rw-r--r--doc/classes/PointLight2D.xml2
-rw-r--r--doc/classes/ProjectSettings.xml29
-rw-r--r--doc/classes/Quaternion.xml13
-rw-r--r--doc/classes/RenderingServer.xml19
-rw-r--r--doc/classes/RichTextLabel.xml8
-rw-r--r--doc/classes/SceneTree.xml2
-rw-r--r--doc/classes/SceneTreeTimer.xml2
-rw-r--r--doc/classes/String.xml4
-rw-r--r--doc/classes/TabBar.xml (renamed from doc/classes/Tabs.xml)12
-rw-r--r--doc/classes/TextEdit.xml11
-rw-r--r--doc/classes/Vector3.xml11
-rw-r--r--doc/translations/Makefile21
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp2
-rw-r--r--editor/SCsub21
-rw-r--r--editor/action_map_editor.cpp10
-rw-r--r--editor/animation_track_editor.cpp177
-rw-r--r--editor/animation_track_editor.h4
-rw-r--r--editor/animation_track_editor_plugins.cpp4
-rw-r--r--editor/code_editor.h2
-rw-r--r--editor/editor_data.h2
-rw-r--r--editor/editor_file_system.cpp3
-rw-r--r--editor/editor_fonts.cpp15
-rw-r--r--editor/editor_help.h3
-rw-r--r--editor/editor_inspector.h4
-rw-r--r--editor/editor_node.cpp146
-rw-r--r--editor/editor_node.h20
-rw-r--r--editor/editor_path.h1
-rw-r--r--editor/editor_properties.cpp3
-rw-r--r--editor/editor_themes.cpp32
-rw-r--r--editor/filesystem_dock.cpp2
-rw-r--r--editor/filesystem_dock.h4
-rw-r--r--editor/find_in_files.cpp2
-rw-r--r--editor/groups_editor.cpp100
-rw-r--r--editor/groups_editor.h15
-rw-r--r--editor/icons/NewKey.svg1
-rw-r--r--editor/icons/TabBar.svg (renamed from editor/icons/Tabs.svg)0
-rw-r--r--editor/import/resource_importer_layered_texture.h2
-rw-r--r--editor/import/resource_importer_scene.cpp29
-rw-r--r--editor/import/resource_importer_scene.h1
-rw-r--r--editor/inspector_dock.cpp4
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h1
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h2
-rw-r--r--editor/plugins/animation_player_editor_plugin.h2
-rw-r--r--editor/plugins/asset_library_editor_plugin.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h10
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp61
-rw-r--r--editor/plugins/node_3d_editor_plugin.h8
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h1
-rw-r--r--editor/plugins/script_editor_plugin.h4
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp268
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h38
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp6
-rw-r--r--editor/plugins/theme_editor_plugin.h5
-rw-r--r--editor/plugins/theme_editor_preview.cpp5
-rw-r--r--editor/plugins/theme_editor_preview.h1
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp15
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp4
-rw-r--r--editor/plugins/tiles/tile_map_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp4
-rw-r--r--editor/plugins/tiles/tile_set_editor.h4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp21
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h2
-rw-r--r--editor/project_settings_editor.h2
-rw-r--r--editor/quick_open.cpp23
-rw-r--r--editor/reparent_dialog.h2
-rw-r--r--editor/scene_tree_dock.h2
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--editor/translations/Makefile21
-rw-r--r--editor/translations/ar.po8
-rw-r--r--editor/translations/ca.po135
-rw-r--r--editor/translations/de.po42
-rw-r--r--editor/translations/es.po47
-rw-r--r--editor/translations/es_AR.po267
-rw-r--r--editor/translations/fa.po36
-rw-r--r--editor/translations/fi.po36
-rw-r--r--editor/translations/fr.po154
-rw-r--r--editor/translations/he.po6
-rw-r--r--editor/translations/ja.po132
-rw-r--r--editor/translations/pt.po90
-rw-r--r--editor/translations/pt_BR.po144
-rw-r--r--editor/translations/ru.po44
-rw-r--r--editor/translations/sv.po11
-rw-r--r--editor/translations/uk.po36
-rw-r--r--editor/translations/zh_CN.po38
-rw-r--r--main/main.cpp23
-rw-r--r--methods.py4
-rw-r--r--misc/dist/osx/editor.entitlements12
-rw-r--r--misc/dist/osx/editor_mono.entitlements18
-rwxr-xr-xmisc/hooks/pre-commit-clang-format10
-rwxr-xr-xmisc/scripts/clang_format.sh2
-rwxr-xr-xmisc/scripts/compare_extension_api.py11
-rw-r--r--modules/bullet/area_bullet.h1
-rw-r--r--modules/bullet/soft_body_bullet.cpp1
-rw-r--r--modules/csg/csg_shape.cpp1
-rw-r--r--modules/denoise/config.py5
-rw-r--r--modules/fbx/tools/import_utils.cpp24
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp3
-rw-r--r--modules/gdnative/nativescript/nativescript.h3
-rw-r--r--modules/gdnative/pluginscript/pluginscript_instance.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.h2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/stringify.gd2
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/gltf/gltf_document.h2
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.h2
-rw-r--r--modules/mbedtls/ssl_context_mbedtls.h2
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h2
-rw-r--r--modules/mono/config.py2
-rw-r--r--modules/mono/csharp_script.cpp16
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs15
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp2
-rw-r--r--modules/raycast/config.py2
-rw-r--r--modules/regex/config.py2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp1
-rw-r--r--modules/text_server_fb/text_server_fb.cpp1
-rw-r--r--modules/theora/config.py2
-rw-r--r--modules/visual_script/visual_script_nodes.h6
-rw-r--r--platform/android/audio_driver_opensl.h4
-rw-r--r--platform/android/java/build.gradle14
-rw-r--r--platform/android/os_android.cpp2
-rw-r--r--platform/android/os_android.h1
-rw-r--r--platform/javascript/package-lock.json6
-rw-r--r--platform/linuxbsd/detect.py7
-rw-r--r--platform/linuxbsd/display_server_x11.cpp49
-rw-r--r--platform/linuxbsd/display_server_x11.h5
-rw-r--r--platform/osx/joypad_osx.h1
-rw-r--r--platform/uwp/os_uwp.h5
-rw-r--r--scene/2d/audio_listener_2d.h2
-rw-r--r--scene/2d/collision_object_2d.cpp4
-rw-r--r--scene/2d/collision_polygon_2d.cpp1
-rw-r--r--scene/2d/collision_shape_2d.cpp2
-rw-r--r--scene/2d/cpu_particles_2d.h7
-rw-r--r--scene/2d/gpu_particles_2d.cpp1
-rw-r--r--scene/2d/mesh_instance_2d.cpp4
-rw-r--r--scene/2d/mesh_instance_2d.h1
-rw-r--r--scene/2d/navigation_agent_2d.cpp4
-rw-r--r--scene/2d/ray_cast_2d.cpp1
-rw-r--r--scene/3d/area_3d.cpp2
-rw-r--r--scene/3d/audio_listener_3d.h3
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/bone_attachment_3d.cpp2
-rw-r--r--scene/3d/camera_3d.cpp2
-rw-r--r--scene/3d/collision_object_3d.cpp4
-rw-r--r--scene/3d/cpu_particles_3d.cpp3
-rw-r--r--scene/3d/cpu_particles_3d.h7
-rw-r--r--scene/3d/decal.cpp1
-rw-r--r--scene/3d/gpu_particles_3d.cpp3
-rw-r--r--scene/3d/light_3d.cpp36
-rw-r--r--scene/3d/light_3d.h1
-rw-r--r--scene/3d/lightmap_gi.cpp1
-rw-r--r--scene/3d/navigation_agent_3d.cpp4
-rw-r--r--scene/3d/navigation_region_3d.cpp2
-rw-r--r--scene/3d/node_3d.cpp107
-rw-r--r--scene/3d/node_3d.h35
-rw-r--r--scene/3d/path_3d.cpp1
-rw-r--r--scene/3d/physics_body_3d.cpp4
-rw-r--r--scene/3d/reflection_probe.cpp1
-rw-r--r--scene/3d/remote_transform_3d.cpp4
-rw-r--r--scene/3d/skeleton_3d.cpp22
-rw-r--r--scene/3d/skeleton_ik_3d.cpp2
-rw-r--r--scene/3d/skeleton_ik_3d.h3
-rw-r--r--scene/3d/soft_dynamic_body_3d.cpp88
-rw-r--r--scene/3d/soft_dynamic_body_3d.h15
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/3d/sprite_3d.h6
-rw-r--r--scene/3d/xr_nodes.cpp2
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/animation_player.h1
-rw-r--r--scene/animation/animation_tree.h6
-rw-r--r--scene/audio/audio_stream_player.cpp2
-rw-r--r--scene/gui/code_edit.cpp2
-rw-r--r--scene/gui/control.cpp28
-rw-r--r--scene/gui/control.h4
-rw-r--r--scene/gui/line_edit.cpp89
-rw-r--r--scene/gui/line_edit.h6
-rw-r--r--scene/gui/popup.h1
-rw-r--r--scene/gui/rich_text_label.cpp15
-rw-r--r--scene/gui/rich_text_label.h4
-rw-r--r--scene/gui/tab_bar.cpp (renamed from scene/gui/tabs.cpp)217
-rw-r--r--scene/gui/tab_bar.h (renamed from scene/gui/tabs.h)19
-rw-r--r--scene/gui/text_edit.cpp99
-rw-r--r--scene/gui/text_edit.h7
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--scene/main/canvas_item.cpp6
-rw-r--r--scene/main/canvas_item.h8
-rw-r--r--scene/main/canvas_layer.cpp8
-rw-r--r--scene/main/scene_tree.h4
-rw-r--r--scene/main/viewport.cpp9
-rw-r--r--scene/register_scene_types.cpp46
-rw-r--r--scene/resources/animation.cpp1653
-rw-r--r--scene/resources/animation.h95
-rw-r--r--scene/resources/default_theme/default_theme.cpp39
-rw-r--r--scene/resources/font.cpp98
-rw-r--r--scene/resources/font.h28
-rw-r--r--scene/resources/mesh.h1
-rw-r--r--scene/resources/shape_2d.h1
-rw-r--r--scene/resources/theme.cpp4
-rw-r--r--servers/audio/effects/audio_effect_limiter.h2
-rw-r--r--servers/audio/effects/audio_effect_record.h1
-rw-r--r--servers/audio/effects/audio_effect_reverb.h2
-rw-r--r--servers/display_server.cpp11
-rw-r--r--servers/display_server.h3
-rw-r--r--servers/physics_2d/godot_body_2d.cpp33
-rw-r--r--servers/physics_2d/godot_body_2d.h5
-rw-r--r--servers/physics_3d/godot_body_3d.cpp19
-rw-r--r--servers/physics_3d/godot_body_3d.h4
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp2
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp1
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp2
-rw-r--r--servers/physics_server_2d_wrap_mt.h2
-rw-r--r--servers/physics_server_3d_wrap_mt.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp4
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl16
-rw-r--r--servers/rendering/renderer_scene_cull.cpp4
-rw-r--r--servers/rendering/shader_language.cpp1
-rw-r--r--servers/rendering_server.cpp15
-rw-r--r--servers/rendering_server.h1
-rw-r--r--tests/test_basis.h28
-rw-r--r--thirdparty/README.md3
-rw-r--r--thirdparty/mbedtls/library/base64.c255
-rw-r--r--thirdparty/mbedtls/patches/pr4819-faster-base64.patch341
266 files changed, 5018 insertions, 2421 deletions
diff --git a/.clang-format b/.clang-format
index 1c26421a7f..9ddb19e57c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,31 +1,41 @@
-# Commented out parameters are those with the same value as base LLVM style
+# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
-# chosen value in case the base style changes (last sync: Clang 6.0.1).
+# chosen value in case the base style changes (last sync: Clang 13.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
-# AlignConsecutiveAssignments: false
-# AlignConsecutiveDeclarations: false
+# AlignArrayOfStructures: None
+# AlignConsecutiveMacros: None
+# AlignConsecutiveAssignments: None
+# AlignConsecutiveBitFields: None
+# AlignConsecutiveDeclarations: None
# AlignEscapedNewlines: Right
-# AlignOperands: true
+# AlignOperands: Align
AlignTrailingComments: false
+# AllowAllArgumentsOnNextLine: true
+# AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
-# AllowShortBlocksOnASingleLine: false
+# AllowShortEnumsOnASingleLine: true
+# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
-# AllowShortIfStatementsOnASingleLine: false
+# AllowShortLambdasOnASingleLine: All
+# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
-# AlwaysBreakTemplateDeclarations: false
+# AlwaysBreakTemplateDeclarations: MultiLine
+# AttributeMacros:
+# - __capability
# BinPackArguments: true
# BinPackParameters: true
# BraceWrapping:
+# AfterCaseLabel: false
# AfterClass: false
-# AfterControlStatement: false
+# AfterControlStatement: Never
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
@@ -35,13 +45,17 @@ AllowShortFunctionsOnASingleLine: Inline
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
+# BeforeLambdaBody: false
+# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakBeforeBinaryOperators: None
+# BreakBeforeConceptDeclarations: true
# BreakBeforeBraces: Attach
# BreakBeforeInheritanceComma: false
+# BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: false
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
@@ -53,14 +67,19 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
+# DeriveLineEnding: true
# DerivePointerAlignment: false
# DisableFormat: false
+# EmptyLineAfterAccessModifier: Never
+# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
# - Q_FOREACH
# - BOOST_FOREACH
+# IfMacros:
+# - KJ_IF_MAYBE
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: '".*"'
@@ -70,13 +89,21 @@ IncludeCategories:
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
+# IncludeIsMainSourceRegex: ''
+# IndentAccessModifiers: false
IndentCaseLabels: true
+# IndentCaseBlocks: false
+# IndentGotoLabels: true
# IndentPPDirectives: None
+# IndentExternBlock: AfterExternBlock
+# IndentRequires: false
IndentWidth: 4
# IndentWrappedFunctionNames: false
+# InsertTrailingCommas: None
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
+# LambdaBodyIndentation: Signature
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
@@ -86,38 +113,72 @@ KeepEmptyLinesAtTheStartOfBlocks: false
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
+# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
+# PenaltyIndentedWhitespace: 0
# PointerAlignment: Right
-# RawStringFormats:
-# - Delimiter: pb
-# Language: TextProto
-# BasedOnStyle: google
+# PPIndentWidth: -1
+# ReferenceAlignment: Pointer
# ReflowComments: true
-# SortIncludes: true
+# ShortNamespaceLines: 1
+# SortIncludes: CaseSensitive
+# SortJavaStaticImport: Before
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
+# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: true
# SpaceBeforeAssignmentOperators: true
+# SpaceBeforeCaseColon: false
+# SpaceBeforeCpp11BracedList: false
+# SpaceBeforeCtorInitializerColon: true
+# SpaceBeforeInheritanceColon: true
# SpaceBeforeParens: ControlStatements
+# SpaceAroundPointerQualifiers: Default
+# SpaceBeforeRangeBasedForLoopColon: true
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
-# SpacesInAngles: false
+# SpaceInEmptyBlock: false
+# SpaceInEmptyParentheses: false
+# SpacesBeforeTrailingComments: 1
+# SpacesInAngles: Never
+# SpacesInContainerLiterals: true
+# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
+## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
+## our comment capitalization at the same time.
+SpacesInLineCommentPrefix:
+ Minimum: 0
+ Maximum: -1
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
+# SpaceBeforeSquareBrackets: false
+# BitFieldColonSpacing: Both
+# StatementAttributeLikeMacros:
+# - Q_EMIT
+# StatementMacros:
+# - Q_UNUSED
+# - QT_REQUIRE_VERSION
TabWidth: 4
+# UseCRLF: false
UseTab: Always
+# WhitespaceSensitiveMacros:
+# - STRINGIZE
+# - PP_STRINGIZE
+# - BOOST_PP_STRINGIZE
+# - NS_SWIFT_NAME
+# - CF_SWIFT_NAME
---
### C++ specific config ###
Language: Cpp
-Standard: Cpp11
+Standard: c++17
---
### ObjC specific config ###
Language: ObjC
-Standard: Cpp11
+# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
+# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
---
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 8a49959a30..f6d11e2efe 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -34,6 +34,7 @@ jobs:
tests: true
sconsflags: use_asan=yes use_ubsan=yes
proj-test: true
+ godot-cpp-test: true
bin: "./bin/godot.linuxbsd.tools.64s"
# Skip 2GiB artifact speeding up action.
artifact: false
@@ -85,6 +86,15 @@ jobs:
run: |
${{ matrix.bin }} --test
+ # Check class reference
+ - name: Check for class reference updates
+ if: ${{ matrix.doc-test }}
+ run: |
+ echo "Running --doctool to see if this changes the public API without updating the documentation."
+ echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
+ ${{ matrix.bin }} --doctool --headless 2>&1 > /dev/null || true
+ git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
+
# Download, unzip and setup SwiftShader library [4466040]
- name: Download SwiftShader
if: ${{ matrix.tests }}
@@ -95,15 +105,6 @@ jobs:
curr="$(pwd)/libvk_swiftshader.so"
sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json
- # Check class reference
- - name: Check for class reference updates
- if: ${{ matrix.doc-test }}
- run: |
- echo "Running --doctool to see if this changes the public API without updating the documentation."
- echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
- VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --doctool . 2>&1 > /dev/null || true
- git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
-
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
- name: Download test project
if: ${{ matrix.proj-test }}
@@ -126,6 +127,46 @@ jobs:
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
+ # Checkout godot-cpp
+ - name: Checkout godot-cpp
+ if: ${{ matrix.godot-cpp-test }}
+ uses: actions/checkout@v2
+ with:
+ repository: godotengine/godot-cpp
+ submodules: 'recursive'
+ path: 'godot-cpp'
+
+ # Check extension API
+ - name: Check for extension api updates
+ if: ${{ matrix.godot-cpp-test }}
+ run: |
+ echo "Running --dump-extension-api to create extensions api."
+ VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --dump-extension-api 2>&1 > /dev/null || true
+ misc/scripts/compare_extension_api.py godot-cpp/godot-headers/extension_api.json extension_api.json
+
+ # Copy new extension API files into place
+ - name: Copy new extension API files into place
+ if: ${{ matrix.godot-cpp-test }}
+ run: |
+ cp -f extension_api.json godot-cpp/godot-headers/
+ cp -f core/extension/gdnative_interface.h godot-cpp/godot-headers/godot/
+
+ # Build godot-cpp library
+ - name: Build godot-cpp library
+ if: ${{ matrix.godot-cpp-test }}
+ run: |
+ cd godot-cpp
+ scons target=${{ matrix.target }} generate_bindings=yes -j2
+ cd ..
+
+ # Build godot-cpp test extension
+ - name: Build godot-cpp test extension
+ if: ${{ matrix.godot-cpp-test }}
+ run: |
+ cd godot-cpp/test
+ scons target=${{ matrix.target }} -j2
+ cd ../..
+
- name: Prepare artifact
if: ${{ matrix.artifact }}
run: |
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/.gitignore b/.gitignore
index 5b3414fe7e..5a8f6aec40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,9 @@
# Documentation generated by doxygen or from classes.xml
doc/_build/
+# Extension API dump
+extension_api.json
+
# Javascript specific
*.bc
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 562cbbdd27..f37e7f5956 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -42,6 +42,8 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
+const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
+
ProjectSettings *ProjectSettings::singleton = nullptr;
ProjectSettings *ProjectSettings::get_singleton() {
@@ -521,7 +523,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
}
// Updating the default value after the project settings have loaded.
- project_data_dir_name = GLOBAL_GET("application/config/project_data_dir_name");
+ bool use_hidden_directory = GLOBAL_GET("application/config/use_hidden_project_data_directory");
+ project_data_dir_name = (use_hidden_directory ? "." : "") + PROJECT_DATA_DIR_NAME_SUFFIX;
// Using GLOBAL_GET on every block for compressing can be slow, so assigning here.
Compression::zstd_long_distance_matching = GLOBAL_GET("compression/formats/zstd/long_distance_matching");
@@ -1094,7 +1097,7 @@ ProjectSettings::ProjectSettings() {
custom_prop_info["application/run/main_scene"] = PropertyInfo(Variant::STRING, "application/run/main_scene", PROPERTY_HINT_FILE, "*.tscn,*.scn,*.res");
GLOBAL_DEF("application/run/disable_stdout", false);
GLOBAL_DEF("application/run/disable_stderr", false);
- project_data_dir_name = GLOBAL_DEF_RST("application/config/project_data_dir_name", ".godot");
+ GLOBAL_DEF_RST("application/config/use_hidden_project_data_directory", true);
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
diff --git a/core/config/project_settings.h b/core/config/project_settings.h
index 82f04b94df..ca37401751 100644
--- a/core/config/project_settings.h
+++ b/core/config/project_settings.h
@@ -42,6 +42,7 @@ class ProjectSettings : public Object {
public:
typedef Map<String, Variant> CustomMap;
+ static const String PROJECT_DATA_DIR_NAME_SUFFIX;
enum {
//properties that are not for built in values begin from this value, so builtin ones are displayed first
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 296aa1f071..c3b43a4274 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -133,6 +133,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2()));
ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event);
ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input);
+ ClassDB::bind_method(D_METHOD("flush_buffered_events"), &Input::flush_buffered_events);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
diff --git a/core/input/input.h b/core/input/input.h
index 6819fc8eb0..f63138a875 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -265,7 +265,6 @@ public:
float get_joy_vibration_duration(int p_device);
uint64_t get_joy_vibration_timestamp(int p_device);
void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = "");
- void parse_joypad_mapping(String p_mapping, bool p_update_existing);
Vector3 get_gravity() const;
Vector3 get_accelerometer() const;
diff --git a/core/io/compression.h b/core/io/compression.h
index cbfed74124..06f26876e5 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -54,8 +54,6 @@ public:
static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD);
static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode);
-
- Compression() {}
};
#endif // COMPRESSION_H
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/io/logger.h b/core/io/logger.h
index f244f70e7e..48b073aa45 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -83,7 +83,6 @@ class RotatedFileLogger : public Logger {
FileAccess *file = nullptr;
- void rotate_file_without_closing();
void close_file();
void clear_old_backups();
void rotate_file();
diff --git a/core/math/basis.cpp b/core/math/basis.cpp
index a7f89522d7..0030cb1144 100644
--- a/core/math/basis.cpp
+++ b/core/math/basis.cpp
@@ -354,7 +354,7 @@ void Basis::rotate(const Quaternion &p_quaternion) {
*this = rotated(p_quaternion);
}
-Vector3 Basis::get_rotation_euler() const {
+Vector3 Basis::get_euler_normalized(EulerOrder p_order) const {
// Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S,
// and returns the Euler angles corresponding to the rotation part, complementing get_scale().
// See the comment in get_scale() for further information.
@@ -365,7 +365,7 @@ Vector3 Basis::get_rotation_euler() const {
m.scale(Vector3(-1, -1, -1));
}
- return m.get_euler();
+ return m.get_euler(p_order);
}
Quaternion Basis::get_rotation_quaternion() const {
@@ -424,218 +424,203 @@ void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) cons
p_angle = -p_angle;
}
-// get_euler_xyz returns a vector containing the Euler angles in the format
-// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
-// (following the convention they are commonly defined in the literature).
-//
-// The current implementation uses XYZ convention (Z is the first rotation),
-// so euler.z is the angle of the (first) rotation around Z axis and so on,
-//
-// And thus, assuming the matrix is a rotation matrix, this function returns
-// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates
-// around the z-axis by a and so on.
-Vector3 Basis::get_euler_xyz() const {
- // Euler angles in XYZ convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz -cy*sz sy
- // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-
- Vector3 euler;
- real_t sy = elements[0][2];
- if (sy < (1.0 - CMP_EPSILON)) {
- if (sy > -(1.0 - CMP_EPSILON)) {
- // is this a pure Y rotation?
- if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
- // return the simplest form (human friendlier in editor and scripts)
- euler.x = 0;
- euler.y = atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
+Vector3 Basis::get_euler(EulerOrder p_order) const {
+ switch (p_order) {
+ case EULER_ORDER_XYZ: {
+ // Euler angles in XYZ convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz -cy*sz sy
+ // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
+ // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
+
+ Vector3 euler;
+ real_t sy = elements[0][2];
+ if (sy < (1.0 - CMP_EPSILON)) {
+ if (sy > -(1.0 - CMP_EPSILON)) {
+ // is this a pure Y rotation?
+ if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
+ // return the simplest form (human friendlier in editor and scripts)
+ euler.x = 0;
+ euler.y = atan2(elements[0][2], elements[0][0]);
+ euler.z = 0;
+ } else {
+ euler.x = Math::atan2(-elements[1][2], elements[2][2]);
+ euler.y = Math::asin(sy);
+ euler.z = Math::atan2(-elements[0][1], elements[0][0]);
+ }
+ } else {
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = -Math_PI / 2.0;
+ euler.z = 0.0;
+ }
} else {
- euler.x = Math::atan2(-elements[1][2], elements[2][2]);
- euler.y = Math::asin(sy);
- euler.z = Math::atan2(-elements[0][1], elements[0][0]);
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = Math_PI / 2.0;
+ euler.z = 0.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_XZY: {
+ // Euler angles in XZY convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy -sz cz*sy
+ // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx
+ // cy*sx*sz cz*sx cx*cy+sx*sz*sy
+
+ Vector3 euler;
+ real_t sz = elements[0][1];
+ if (sz < (1.0 - CMP_EPSILON)) {
+ if (sz > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(elements[2][1], elements[1][1]);
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
+ euler.z = Math::asin(-sz);
+ } else {
+ // It's -1
+ euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = Math_PI / 2.0;
+ }
+ } else {
+ // It's 1
+ euler.x = -Math::atan2(elements[1][2], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = -Math_PI / 2.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_YXZ: {
+ // Euler angles in YXZ convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
+ // cx*sz cx*cz -sx
+ // cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
+
+ Vector3 euler;
+
+ real_t m12 = elements[1][2];
+
+ if (m12 < (1 - CMP_EPSILON)) {
+ if (m12 > -(1 - CMP_EPSILON)) {
+ // is this a pure X rotation?
+ if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
+ // return the simplest form (human friendlier in editor and scripts)
+ euler.x = atan2(-m12, elements[1][1]);
+ euler.y = 0;
+ euler.z = 0;
+ } else {
+ euler.x = asin(-m12);
+ euler.y = atan2(elements[0][2], elements[2][2]);
+ euler.z = atan2(elements[1][0], elements[1][1]);
+ }
+ } else { // m12 == -1
+ euler.x = Math_PI * 0.5;
+ euler.y = atan2(elements[0][1], elements[0][0]);
+ euler.z = 0;
+ }
+ } else { // m12 == 1
+ euler.x = -Math_PI * 0.5;
+ euler.y = -atan2(elements[0][1], elements[0][0]);
+ euler.z = 0;
}
- } else {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = -Math_PI / 2.0;
- euler.z = 0.0;
- }
- } else {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = Math_PI / 2.0;
- euler.z = 0.0;
- }
- return euler;
-}
-
-// set_euler_xyz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// The current implementation uses XYZ convention (Z is the first rotation).
-void Basis::set_euler_xyz(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- //optimizer will optimize away all this anyway
- *this = xmat * (ymat * zmat);
-}
-
-Vector3 Basis::get_euler_xzy() const {
- // Euler angles in XZY convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy -sz cz*sy
- // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx
- // cy*sx*sz cz*sx cx*cy+sx*sz*sy
-
- Vector3 euler;
- real_t sz = elements[0][1];
- if (sz < (1.0 - CMP_EPSILON)) {
- if (sz > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(elements[2][1], elements[1][1]);
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = Math::asin(-sz);
- } else {
- // It's -1
- euler.x = -Math::atan2(elements[1][2], elements[2][2]);
- euler.y = 0.0;
- euler.z = Math_PI / 2.0;
- }
- } else {
- // It's 1
- euler.x = -Math::atan2(elements[1][2], elements[2][2]);
- euler.y = 0.0;
- euler.z = -Math_PI / 2.0;
- }
- return euler;
-}
-
-void Basis::set_euler_xzy(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = xmat * zmat * ymat;
-}
-
-Vector3 Basis::get_euler_yzx() const {
- // Euler angles in YZX convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
- // sz cz*cx -cz*sx
- // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
-
- Vector3 euler;
- real_t sz = elements[1][0];
- if (sz < (1.0 - CMP_EPSILON)) {
- if (sz > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(-elements[1][2], elements[1][1]);
- euler.y = Math::atan2(-elements[2][0], elements[0][0]);
- euler.z = Math::asin(sz);
- } else {
- // It's -1
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = 0.0;
- euler.z = -Math_PI / 2.0;
- }
- } else {
- // It's 1
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = 0.0;
- euler.z = Math_PI / 2.0;
- }
- return euler;
-}
-
-void Basis::set_euler_yzx(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = ymat * zmat * xmat;
-}
-
-// get_euler_yxz returns a vector containing the Euler angles in the YXZ convention,
-// as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned
-// as the x, y, and z components of a Vector3 respectively.
-Vector3 Basis::get_euler_yxz() const {
- // Euler angles in YXZ convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
- // cx*sz cx*cz -sx
- // cy*sx*sz-cz*sy cy*cz*sx+sy*sz cy*cx
-
- Vector3 euler;
-
- real_t m12 = elements[1][2];
- if (m12 < (1 - CMP_EPSILON)) {
- if (m12 > -(1 - CMP_EPSILON)) {
- // is this a pure X rotation?
- if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
- // return the simplest form (human friendlier in editor and scripts)
- euler.x = atan2(-m12, elements[1][1]);
- euler.y = 0;
+ return euler;
+ } break;
+ case EULER_ORDER_YZX: {
+ // Euler angles in YZX convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
+ // sz cz*cx -cz*sx
+ // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
+
+ Vector3 euler;
+ real_t sz = elements[1][0];
+ if (sz < (1.0 - CMP_EPSILON)) {
+ if (sz > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(-elements[1][2], elements[1][1]);
+ euler.y = Math::atan2(-elements[2][0], elements[0][0]);
+ euler.z = Math::asin(sz);
+ } else {
+ // It's -1
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = -Math_PI / 2.0;
+ }
+ } else {
+ // It's 1
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = 0.0;
+ euler.z = Math_PI / 2.0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_ZXY: {
+ // Euler angles in ZXY convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
+ // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx
+ // -cx*sy sx cx*cy
+ Vector3 euler;
+ real_t sx = elements[2][1];
+ if (sx < (1.0 - CMP_EPSILON)) {
+ if (sx > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::asin(sx);
+ euler.y = Math::atan2(-elements[2][0], elements[2][2]);
+ euler.z = Math::atan2(-elements[0][1], elements[1][1]);
+ } else {
+ // It's -1
+ euler.x = -Math_PI / 2.0;
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
+ euler.z = 0;
+ }
+ } else {
+ // It's 1
+ euler.x = Math_PI / 2.0;
+ euler.y = Math::atan2(elements[0][2], elements[0][0]);
euler.z = 0;
+ }
+ return euler;
+ } break;
+ case EULER_ORDER_ZYX: {
+ // Euler angles in ZYX convention.
+ // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
+ //
+ // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy
+ // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
+ // -sy cy*sx cy*cx
+ Vector3 euler;
+ real_t sy = elements[2][0];
+ if (sy < (1.0 - CMP_EPSILON)) {
+ if (sy > -(1.0 - CMP_EPSILON)) {
+ euler.x = Math::atan2(elements[2][1], elements[2][2]);
+ euler.y = Math::asin(-sy);
+ euler.z = Math::atan2(elements[1][0], elements[0][0]);
+ } else {
+ // It's -1
+ euler.x = 0;
+ euler.y = Math_PI / 2.0;
+ euler.z = -Math::atan2(elements[0][1], elements[1][1]);
+ }
} else {
- euler.x = asin(-m12);
- euler.y = atan2(elements[0][2], elements[2][2]);
- euler.z = atan2(elements[1][0], elements[1][1]);
+ // It's 1
+ euler.x = 0;
+ euler.y = -Math_PI / 2.0;
+ euler.z = -Math::atan2(elements[0][1], elements[1][1]);
}
- } else { // m12 == -1
- euler.x = Math_PI * 0.5;
- euler.y = atan2(elements[0][1], elements[0][0]);
- euler.z = 0;
+ return euler;
+ } break;
+ default: {
+ ERR_FAIL_V_MSG(Vector3(), "Invalid parameter for get_euler(order)");
}
- } else { // m12 == 1
- euler.x = -Math_PI * 0.5;
- euler.y = -atan2(elements[0][1], elements[0][0]);
- euler.z = 0;
}
-
- return euler;
+ return Vector3();
}
-// set_euler_yxz expects a vector containing the Euler angles in the format
-// (ax,ay,az), where ax is the angle of rotation around x axis,
-// and similar for other axes.
-// The current implementation uses YXZ convention (Z is the first rotation).
-void Basis::set_euler_yxz(const Vector3 &p_euler) {
+void Basis::set_euler(const Vector3 &p_euler, EulerOrder p_order) {
real_t c, s;
c = Math::cos(p_euler.x);
@@ -650,102 +635,29 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) {
s = Math::sin(p_euler.z);
Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
- //optimizer will optimize away all this anyway
- *this = ymat * xmat * zmat;
-}
-
-Vector3 Basis::get_euler_zxy() const {
- // Euler angles in ZXY convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
- // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx
- // -cx*sy sx cx*cy
- Vector3 euler;
- real_t sx = elements[2][1];
- if (sx < (1.0 - CMP_EPSILON)) {
- if (sx > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::asin(sx);
- euler.y = Math::atan2(-elements[2][0], elements[2][2]);
- euler.z = Math::atan2(-elements[0][1], elements[1][1]);
- } else {
- // It's -1
- euler.x = -Math_PI / 2.0;
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
+ switch (p_order) {
+ case EULER_ORDER_XYZ: {
+ *this = xmat * (ymat * zmat);
+ } break;
+ case EULER_ORDER_XZY: {
+ *this = xmat * zmat * ymat;
+ } break;
+ case EULER_ORDER_YXZ: {
+ *this = ymat * xmat * zmat;
+ } break;
+ case EULER_ORDER_YZX: {
+ *this = ymat * zmat * xmat;
+ } break;
+ case EULER_ORDER_ZXY: {
+ *this = zmat * xmat * ymat;
+ } break;
+ case EULER_ORDER_ZYX: {
+ *this = zmat * ymat * xmat;
+ } break;
+ default: {
+ ERR_FAIL_MSG("Invalid order parameter for set_euler(vec3,order)");
}
- } else {
- // It's 1
- euler.x = Math_PI / 2.0;
- euler.y = Math::atan2(elements[0][2], elements[0][0]);
- euler.z = 0;
}
- return euler;
-}
-
-void Basis::set_euler_zxy(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = zmat * xmat * ymat;
-}
-
-Vector3 Basis::get_euler_zyx() const {
- // Euler angles in ZYX convention.
- // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
- //
- // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy
- // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
- // -sy cy*sx cy*cx
- Vector3 euler;
- real_t sy = elements[2][0];
- if (sy < (1.0 - CMP_EPSILON)) {
- if (sy > -(1.0 - CMP_EPSILON)) {
- euler.x = Math::atan2(elements[2][1], elements[2][2]);
- euler.y = Math::asin(-sy);
- euler.z = Math::atan2(elements[1][0], elements[0][0]);
- } else {
- // It's -1
- euler.x = 0;
- euler.y = Math_PI / 2.0;
- euler.z = -Math::atan2(elements[0][1], elements[1][1]);
- }
- } else {
- // It's 1
- euler.x = 0;
- euler.y = -Math_PI / 2.0;
- euler.z = -Math::atan2(elements[0][1], elements[1][1]);
- }
- return euler;
-}
-
-void Basis::set_euler_zyx(const Vector3 &p_euler) {
- real_t c, s;
-
- c = Math::cos(p_euler.x);
- s = Math::sin(p_euler.x);
- Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c);
-
- c = Math::cos(p_euler.y);
- s = Math::sin(p_euler.y);
- Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c);
-
- c = Math::cos(p_euler.z);
- s = Math::sin(p_euler.z);
- Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0);
-
- *this = zmat * ymat * xmat;
}
bool Basis::is_equal_approx(const Basis &p_basis) const {
diff --git a/core/math/basis.h b/core/math/basis.h
index eb107d7e4e..617d005f19 100644
--- a/core/math/basis.h
+++ b/core/math/basis.h
@@ -85,40 +85,35 @@ public:
void rotate(const Quaternion &p_quaternion);
Basis rotated(const Quaternion &p_quaternion) const;
- Vector3 get_rotation_euler() const;
+ enum EulerOrder {
+ EULER_ORDER_XYZ,
+ EULER_ORDER_XZY,
+ EULER_ORDER_YXZ,
+ EULER_ORDER_YZX,
+ EULER_ORDER_ZXY,
+ EULER_ORDER_ZYX
+ };
+
+ Vector3 get_euler_normalized(EulerOrder p_order = EULER_ORDER_YXZ) const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
Quaternion get_rotation_quaternion() const;
- Vector3 get_rotation() const { return get_rotation_euler(); };
void rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction);
Vector3 rotref_posscale_decomposition(Basis &rotref) const;
- Vector3 get_euler_xyz() const;
- void set_euler_xyz(const Vector3 &p_euler);
-
- Vector3 get_euler_xzy() const;
- void set_euler_xzy(const Vector3 &p_euler);
-
- Vector3 get_euler_yzx() const;
- void set_euler_yzx(const Vector3 &p_euler);
-
- Vector3 get_euler_yxz() const;
- void set_euler_yxz(const Vector3 &p_euler);
-
- Vector3 get_euler_zxy() const;
- void set_euler_zxy(const Vector3 &p_euler);
-
- Vector3 get_euler_zyx() const;
- void set_euler_zyx(const Vector3 &p_euler);
+ Vector3 get_euler(EulerOrder p_order = EULER_ORDER_YXZ) const;
+ void set_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ);
+ static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) {
+ Basis b;
+ b.set_euler(p_euler, p_order);
+ return b;
+ }
Quaternion get_quaternion() const;
void set_quaternion(const Quaternion &p_quaternion);
- Vector3 get_euler() const { return get_euler_yxz(); }
- void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
-
void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
@@ -250,9 +245,6 @@ public:
Basis(const Quaternion &p_quaternion) { set_quaternion(p_quaternion); };
Basis(const Quaternion &p_quaternion, const Vector3 &p_scale) { set_quaternion_scale(p_quaternion, p_scale); }
- Basis(const Vector3 &p_euler) { set_euler(p_euler); }
- Basis(const Vector3 &p_euler, const Vector3 &p_scale) { set_euler_scale(p_euler, p_scale); }
-
Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
Basis(const Vector3 &p_axis, real_t p_phi, const Vector3 &p_scale) { set_axis_angle_scale(p_axis, p_phi, p_scale); }
static Basis from_scale(const Vector3 &p_scale);
diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp
index f67035c803..684814b1ae 100644
--- a/core/math/convex_hull.cpp
+++ b/core/math/convex_hull.cpp
@@ -594,8 +594,6 @@ private:
IntermediateHull() {
}
-
- void print();
};
enum Orientation { NONE,
diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h
index 8e5830f9b3..6010159597 100644
--- a/core/math/geometry_2d.h
+++ b/core/math/geometry_2d.h
@@ -37,8 +37,6 @@
#include "core/templates/vector.h"
class Geometry2D {
- Geometry2D();
-
public:
static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) {
Vector2 d1 = q1 - p1; // Direction vector of segment S1.
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 766689e222..6a59b34585 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -36,8 +36,6 @@
#include "core/templates/vector.h"
class Geometry3D {
- Geometry3D();
-
public:
static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
// Do the function 'd' as defined by pb. I think it's a dot product of some sort.
diff --git a/core/math/quaternion.cpp b/core/math/quaternion.cpp
index 3f1d2c58e5..944474686a 100644
--- a/core/math/quaternion.cpp
+++ b/core/math/quaternion.cpp
@@ -44,7 +44,7 @@ real_t Quaternion::angle_to(const Quaternion &p_to) const {
// This implementation uses XYZ convention (Z is the first rotation).
Vector3 Quaternion::get_euler_xyz() const {
Basis m(*this);
- return m.get_euler_xyz();
+ return m.get_euler(Basis::EULER_ORDER_XYZ);
}
// get_euler_yxz returns a vector containing the Euler angles in the format
@@ -56,7 +56,7 @@ Vector3 Quaternion::get_euler_yxz() const {
ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized.");
#endif
Basis m(*this);
- return m.get_euler_yxz();
+ return m.get_euler(Basis::EULER_ORDER_YXZ);
}
void Quaternion::operator*=(const Quaternion &p_q) {
@@ -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/os/memory.h b/core/os/memory.h
index f67384a17e..ac56a12330 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -42,7 +42,6 @@
#endif
class Memory {
- Memory();
#ifdef DEBUG_ENABLED
static SafeNumeric<uint64_t> mem_usage;
static SafeNumeric<uint64_t> max_usage;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 7404ffdcd5..5892f91ff3 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -431,6 +431,15 @@ bool OS::has_feature(const String &p_feature) {
if (p_feature == "arm") {
return true;
}
+#elif defined(__riscv)
+#if __riscv_xlen == 8
+ if (p_feature == "rv64") {
+ return true;
+ }
+#endif
+ if (p_feature == "riscv") {
+ return true;
+ }
#endif
if (_check_internal_feature_support(p_feature)) {
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index daeb7fbd17..397743fb6e 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -2137,7 +2137,7 @@ int64_t String::hex_to_int() const {
s++;
}
- if (len > 2 && s[0] == '0' && s[1] == 'x') {
+ if (len > 2 && s[0] == '0' && lower_case(s[1]) == 'x') {
s += 2;
}
@@ -2151,7 +2151,7 @@ int64_t String::hex_to_int() const {
} else if (c >= 'a' && c <= 'f') {
n = (c - 'a') + 10;
} else {
- return 0;
+ ERR_FAIL_COND_V_MSG(true, 0, "Invalid hexadecimal notation character \"" + chr(*s) + "\" in string \"" + *this + "\".");
}
// Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error
bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0');
@@ -2178,7 +2178,7 @@ int64_t String::bin_to_int() const {
s++;
}
- if (len > 2 && s[0] == '0' && s[1] == 'b') {
+ if (len > 2 && s[0] == '0' && lower_case(s[1]) == 'b') {
s += 2;
}
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index 8592a1dc62..f06d767cf5 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -88,6 +88,7 @@ struct VariantCaster<const T &> {
VARIANT_ENUM_CAST(Object::ConnectFlags);
VARIANT_ENUM_CAST(Vector3::Axis);
+VARIANT_ENUM_CAST(Basis::EulerOrder);
VARIANT_ENUM_CAST(Error);
VARIANT_ENUM_CAST(Side);
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 3214fc125d..81428caca1 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -313,7 +313,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
case BASIS: {
static const Type valid[] = {
QUATERNION,
- VECTOR3,
NIL
};
@@ -620,7 +619,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
case BASIS: {
static const Type valid[] = {
QUATERNION,
- VECTOR3,
NIL
};
@@ -1889,8 +1887,6 @@ Variant::operator Basis() const {
return *_data._basis;
} else if (type == QUATERNION) {
return *reinterpret_cast<const Quaternion *>(_data._mem);
- } else if (type == VECTOR3) {
- return Basis(*reinterpret_cast<const Vector3 *>(_data._mem));
} else if (type == TRANSFORM3D) { // unexposed in Variant::can_convert?
return _data._transform3d->basis;
} else {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 6284caae2d..ec3a6a5ca8 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 */
@@ -1727,7 +1731,7 @@ static void _register_variant_builtin_methods() {
bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, real_t) const>(&Basis::rotated), sarray("axis", "phi"), varray());
bind_method(Basis, scaled, sarray("scale"), varray());
bind_method(Basis, get_scale, sarray(), varray());
- bind_method(Basis, get_euler, sarray(), varray());
+ bind_method(Basis, get_euler, sarray("order"), varray(Basis::EULER_ORDER_YXZ));
bind_method(Basis, tdotx, sarray("with"), varray());
bind_method(Basis, tdoty, sarray("with"), varray());
bind_method(Basis, tdotz, sarray("with"), varray());
@@ -1737,6 +1741,7 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, get_rotation_quaternion, sarray(), varray());
bind_static_method(Basis, looking_at, sarray("target", "up"), varray(Vector3(0, 1, 0)));
bind_static_method(Basis, from_scale, sarray("scale"), varray());
+ bind_static_method(Basis, from_euler, sarray("euler", "order"), varray(Basis::EULER_ORDER_YXZ));
/* AABB */
@@ -2105,6 +2110,13 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1));
_VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1));
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_XYZ", Basis::EULER_ORDER_XYZ);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_XZY", Basis::EULER_ORDER_XZY);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_YXZ", Basis::EULER_ORDER_YXZ);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_YZX", Basis::EULER_ORDER_YZX);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZXY", Basis::EULER_ORDER_ZXY);
+ _VariantCall::add_constant(Variant::BASIS, "EULER_ORDER_ZYX", Basis::EULER_ORDER_ZYX);
+
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D());
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0));
_VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0));
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
index 6aba7d7d58..5c14f30180 100644
--- a/core/variant/variant_construct.cpp
+++ b/core/variant/variant_construct.cpp
@@ -128,10 +128,10 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Quaternion>>(sarray());
add_constructor<VariantConstructor<Quaternion, Quaternion>>(sarray("from"));
add_constructor<VariantConstructor<Quaternion, Basis>>(sarray("from"));
- add_constructor<VariantConstructor<Quaternion, Vector3>>(sarray("euler"));
add_constructor<VariantConstructor<Quaternion, Vector3, double>>(sarray("axis", "angle"));
add_constructor<VariantConstructor<Quaternion, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
add_constructor<VariantConstructor<Quaternion, double, double, double, double>>(sarray("x", "y", "z", "w"));
+ add_constructor<VariantConstructor<Quaternion, Vector3>>(sarray("euler_yxz"));
add_constructor<VariantConstructNoArgs<::AABB>>(sarray());
add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
@@ -140,7 +140,6 @@ void Variant::_register_variant_constructors() {
add_constructor<VariantConstructNoArgs<Basis>>(sarray());
add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
add_constructor<VariantConstructor<Basis, Quaternion>>(sarray("from"));
- add_constructor<VariantConstructor<Basis, Vector3>>(sarray("euler"));
add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi"));
add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 37383ff2ec..2ba24b5af8 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -757,6 +757,12 @@ VARIANT_ACCESSOR_NUMBER(Error)
VARIANT_ACCESSOR_NUMBER(Side)
template <>
+struct VariantInternalAccessor<Basis::EulerOrder> {
+ static _FORCE_INLINE_ Basis::EulerOrder get(const Variant *v) { return Basis::EulerOrder(*VariantInternal::get_int(v)); }
+ static _FORCE_INLINE_ void set(Variant *v, Basis::EulerOrder p_value) { *VariantInternal::get_int(v) = p_value; }
+};
+
+template <>
struct VariantInternalAccessor<ObjectID> {
static _FORCE_INLINE_ ObjectID get(const Variant *v) { return ObjectID(*VariantInternal::get_int(v)); }
static _FORCE_INLINE_ void set(Variant *v, ObjectID p_value) { *VariantInternal::get_int(v) = p_value; }
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/Basis.xml b/doc/classes/Basis.xml
index 7f0d4cbbe3..6215c658c3 100644
--- a/doc/classes/Basis.xml
+++ b/doc/classes/Basis.xml
@@ -42,14 +42,6 @@
</method>
<method name="Basis" qualifiers="constructor">
<return type="Basis" />
- <argument index="0" name="euler" type="Vector3" />
- <description>
- Constructs a pure rotation basis matrix from the given Euler angles (in the YXZ convention: when *composing*, first Y, then X, and Z last), given in the vector format as (X angle, Y angle, Z angle).
- Consider using the [Quaternion] constructor instead, which uses a quaternion instead of Euler angles.
- </description>
- </method>
- <method name="Basis" qualifiers="constructor">
- <return type="Basis" />
<argument index="0" name="from" type="Quaternion" />
<description>
Constructs a pure rotation basis matrix from the given quaternion.
@@ -71,6 +63,13 @@
A negative determinant means the basis has a negative scale. A zero determinant means the basis isn't invertible, and is usually considered invalid.
</description>
</method>
+ <method name="from_euler" qualifiers="static">
+ <return type="Basis" />
+ <argument index="0" name="euler" type="Vector3" />
+ <argument index="1" name="order" type="int" default="2" />
+ <description>
+ </description>
+ </method>
<method name="from_scale" qualifiers="static">
<return type="Basis" />
<argument index="0" name="scale" type="Vector3" />
@@ -80,6 +79,7 @@
</method>
<method name="get_euler" qualifiers="const">
<return type="Vector3" />
+ <argument index="0" name="order" type="int" default="2" />
<description>
Returns the basis's rotation in the form of Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last). The returned vector contains the rotation angles in the format (X angle, Y angle, Z angle).
Consider using the [method get_rotation_quaternion] method instead, which returns a [Quaternion] quaternion instead of Euler angles.
@@ -248,6 +248,18 @@
</member>
</members>
<constants>
+ <constant name="EULER_ORDER_XYZ" value="0">
+ </constant>
+ <constant name="EULER_ORDER_XZY" value="1">
+ </constant>
+ <constant name="EULER_ORDER_YXZ" value="2">
+ </constant>
+ <constant name="EULER_ORDER_YZX" value="3">
+ </constant>
+ <constant name="EULER_ORDER_ZXY" value="4">
+ </constant>
+ <constant name="EULER_ORDER_ZYX" value="5">
+ </constant>
<constant name="IDENTITY" value="Basis(1, 0, 0, 0, 1, 0, 0, 0, 1)">
The identity basis, with no rotation or scaling applied.
This is identical to calling [code]Basis()[/code] without any parameters. This constant can be used to make your code clearer, and for consistency with C#.
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 738594ea5d..7be18c1d5c 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -53,7 +53,7 @@
<argument index="1" name="pos" type="Vector2" />
<argument index="2" name="char" type="String" />
<argument index="3" name="next" type="String" default="&quot;&quot;" />
- <argument index="4" name="size" type="int" default="-1" />
+ <argument index="4" name="size" type="int" default="16" />
<argument index="5" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="6" name="outline_size" type="int" default="0" />
<argument index="7" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -146,7 +146,7 @@
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
<argument index="5" name="max_lines" type="int" default="-1" />
- <argument index="6" name="size" type="int" default="-1" />
+ <argument index="6" name="size" type="int" default="16" />
<argument index="7" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="8" name="outline_size" type="int" default="0" />
<argument index="9" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
@@ -238,7 +238,7 @@
<argument index="2" name="text" type="String" />
<argument index="3" name="align" type="int" enum="HAlign" default="0" />
<argument index="4" name="width" type="float" default="-1" />
- <argument index="5" name="size" type="int" default="-1" />
+ <argument index="5" name="size" type="int" default="16" />
<argument index="6" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
<argument index="7" name="outline_size" type="int" default="0" />
<argument index="8" name="outline_modulate" type="Color" default="Color(1, 1, 1, 0)" />
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 332d171457..63e3eb7a5f 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1044,7 +1044,7 @@
<member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)">
The node's scale, relative to its [member rect_size]. Change this property to scale the node around its [member rect_pivot_offset]. The Control's [member hint_tooltip] will also scale according to this value.
[b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=https://docs.godotengine.org/en/latest/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually.
- [b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]yield(get_tree(), "process_frame")[/code] then set its [member rect_scale] property.
+ [b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]await get_tree().process_frame[/code] then set its [member rect_scale] property.
</member>
<member name="rect_size" type="Vector2" setter="_set_size" getter="get_size" default="Vector2(0, 0)">
The size of the node's bounding rectangle, in pixels. [Container] nodes update this property automatically.
diff --git a/doc/classes/DirectionalLight2D.xml b/doc/classes/DirectionalLight2D.xml
index 317cf6e66c..1e5c9bc09a 100644
--- a/doc/classes/DirectionalLight2D.xml
+++ b/doc/classes/DirectionalLight2D.xml
@@ -8,7 +8,7 @@
</tutorials>
<members>
<member name="height" type="float" setter="set_height" getter="get_height" default="0.0">
- The height of the light. Used with 2D normal mapping.
+ The height of the light. Used with 2D normal mapping. Ranges from 0 (parallel to the plane) to 1 (perpendicular to the plane).
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="10000.0">
</member>
diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml
index f2a6e5b6f8..44d982cbcc 100644
--- a/doc/classes/DirectionalLight3D.xml
+++ b/doc/classes/DirectionalLight3D.xml
@@ -11,13 +11,13 @@
</tutorials>
<members>
<member name="directional_shadow_blend_splits" type="bool" setter="set_blend_splits" getter="is_blend_splits_enabled" default="false">
- If [code]true[/code], shadow detail is sacrificed in exchange for smoother transitions between splits. This is ignored when [member directional_shadow_mode] is [code]SHADOW_ORTHOGONAL[/code].
+ If [code]true[/code], shadow detail is sacrificed in exchange for smoother transitions between splits. Enabling shadow blend splitting also has a moderate performance cost. This is ignored when [member directional_shadow_mode] is [constant SHADOW_ORTHOGONAL].
</member>
<member name="directional_shadow_fade_start" type="float" setter="set_param" getter="get_param" default="0.8">
- Proportion of [member directional_shadow_max_distance] at which point the shadow starts to fade. At [member directional_shadow_max_distance] the shadow will disappear.
+ Proportion of [member directional_shadow_max_distance] at which point the shadow starts to fade. At [member directional_shadow_max_distance], the shadow will disappear. The default value is a balance between smooth fading and distant shadow visibility. If the camera moves fast and the [member directional_shadow_max_distance] is low, consider lowering [member directional_shadow_fade_start] below [code]0.8[/code] to make shadow transitions less noticeable. On the other hand, if you tuned [member directional_shadow_max_distance] to cover the entire scene, you can set [member directional_shadow_fade_start] to [code]1.0[/code] to prevent the shadow from fading in the distance (it will suddenly cut off instead).
</member>
<member name="directional_shadow_max_distance" type="float" setter="set_param" getter="get_param" default="100.0">
- The maximum distance for shadow splits.
+ The maximum distance for shadow splits. Increasing this value will make directional shadows visible from further away, at the cost of lower overall shadow detail and performance (since more objects need to be included in the directional shadow rendering).
</member>
<member name="directional_shadow_mode" type="int" setter="set_shadow_mode" getter="get_shadow_mode" enum="DirectionalLight3D.ShadowMode" default="2">
The light's shadow rendering algorithm. See [enum ShadowMode].
@@ -26,13 +26,13 @@
Sets the size of the directional shadow pancake. The pancake offsets the start of the shadow's camera frustum to provide a higher effective depth resolution for the shadow. However, a high pancake size can cause artifacts in the shadows of large objects that are close to the edge of the frustum. Reducing the pancake size can help. Setting the size to [code]0[/code] turns off the pancaking effect.
</member>
<member name="directional_shadow_split_1" type="float" setter="set_param" getter="get_param" default="0.1">
- The distance from camera to shadow split 1. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_2_SPLITS[/code] or [code]SHADOW_PARALLEL_4_SPLITS[/code].
+ The distance from camera to shadow split 1. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_2_SPLITS] or [constant SHADOW_PARALLEL_4_SPLITS].
</member>
<member name="directional_shadow_split_2" type="float" setter="set_param" getter="get_param" default="0.2">
- The distance from shadow split 1 to split 2. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_4_SPLITS[/code].
+ The distance from shadow split 1 to split 2. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS].
</member>
<member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5">
- The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_4_SPLITS[/code].
+ The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [constant SHADOW_PARALLEL_4_SPLITS].
</member>
<member name="shadow_bias" type="float" setter="set_param" getter="get_param" override="true" default="0.1" />
<member name="use_in_sky_only" type="bool" setter="set_sky_only" getter="is_sky_only" default="false">
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 7a467c03c1..92d6a220d2 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -13,6 +13,13 @@
Returns the user's clipboard as a string if possible.
</description>
</method>
+ <method name="clipboard_get_primary" qualifiers="const">
+ <return type="String" />
+ <description>
+ Returns the user's primary clipboard as a string if possible.
+ [b]Note:[/b] This method is only implemented on Linux.
+ </description>
+ </method>
<method name="clipboard_set">
<return type="void" />
<argument index="0" name="clipboard" type="String" />
@@ -20,6 +27,14 @@
Sets the user's clipboard content to the given string.
</description>
</method>
+ <method name="clipboard_set_primary">
+ <return type="void" />
+ <argument index="0" name="clipboard_primary" type="String" />
+ <description>
+ Sets the user's primary clipboard content to the given string.
+ [b]Note:[/b] This method is only implemented on Linux.
+ </description>
+ </method>
<method name="console_set_visible">
<return type="void" />
<argument index="0" name="console_visible" type="bool" />
@@ -804,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/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index 6011a5411d..cb33f159ef 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
[EditorImportPlugin]s provide a way to extend the editor's resource import functionality. Use them to import resources from custom files or to provide alternatives to the editor's existing importers.
- EditorImportPlugins work by associating with specific file extensions and a resource type. See [method _get_recognized_extensions] and [method _get_resource_type]. They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].godot/imported[/code] directory (see [member ProjectSettings.application/config/project_data_dir_name]).
+ EditorImportPlugins work by associating with specific file extensions and a resource type. See [method _get_recognized_extensions] and [method _get_resource_type]. They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].godot/imported[/code] directory (see [member ProjectSettings.application/config/use_hidden_project_data_directory]).
Below is an example EditorImportPlugin that imports a [Mesh] from a file with the extension ".special" or ".spec":
[codeblocks]
[gdscript]
@@ -198,7 +198,7 @@
<method name="_get_save_extension" qualifiers="virtual const">
<return type="String" />
<description>
- Gets the extension used to save this resource in the [code].godot/imported[/code] directory (see [member ProjectSettings.application/config/project_data_dir_name]).
+ Gets the extension used to save this resource in the [code].godot/imported[/code] directory (see [member ProjectSettings.application/config/use_hidden_project_data_directory]).
</description>
</method>
<method name="_get_visible_name" qualifiers="virtual const">
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/Input.xml b/doc/classes/Input.xml
index 88e4a67615..1fded42db2 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -37,6 +37,13 @@
Adds a new mapping entry (in SDL2 format) to the mapping database. Optionally update already connected devices.
</description>
</method>
+ <method name="flush_buffered_events">
+ <return type="void" />
+ <description>
+ Sends all input events which are in the current buffer to the game loop. These events may have been buffered as a result of accumulated input ([method set_use_accumulated_input]) or agile input flushing ([member ProjectSettings.input_devices/buffering/agile_event_flushing]).
+ The engine will already do this itself at key execution points (at least once per frame). However, this can be useful in advanced cases where you want precise control over the timing of event handling.
+ </description>
+ </method>
<method name="get_accelerometer" qualifiers="const">
<return type="Vector3" />
<description>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 75f2d72396..a37bab9b11 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -222,6 +222,10 @@
[/csharp]
[/codeblocks]
</member>
+ <member name="middle_mouse_paste_enabled" type="bool" setter="set_middle_mouse_paste_enabled" getter="is_middle_mouse_paste_enabled" default="true">
+ If [code]false[/code], using middle mouse button to paste clipboard will be disabled.
+ [b]Note:[/b] This method is only implemented on Linux.
+ </member>
<member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" />
<member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6">
Opacity of the [member placeholder_text]. From [code]0[/code] to [code]1[/code].
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 28acd77a39..2ca664e2b5 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -264,16 +264,28 @@
</method>
</methods>
<members>
+ <member name="basis" type="Basis" setter="set_basis" getter="get_basis">
+ Direct access to the 3x3 basis of the [Transform3D] property.
+ </member>
<member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
<member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)">
Local position or translation of this node relative to the parent. This is equivalent to [code]transform.origin[/code].
</member>
+ <member name="quaternion" type="Quaternion" setter="set_quaternion" getter="get_quaternion">
+ Access to the node rotation as a [Quaternion]. This property is ideal for tweening complex rotations.
+ </member>
<member name="rotation" type="Vector3" setter="set_rotation" getter="get_rotation" default="Vector3(0, 0, 0)">
- Rotation part of the local transformation in radians, specified in terms of YXZ-Euler angles in the format (X angle, Y angle, Z angle).
+ Rotation part of the local transformation in radians, specified in terms of Euler angles. The angles construct a rotaton in the order specified by the [member rotation_order] property.
[b]Note:[/b] In the mathematical sense, rotation is a matrix and not a vector. The three Euler angles, which are the three independent parameters of the Euler-angle parametrization of the rotation matrix, are stored in a [Vector3] data structure not because the rotation is a vector, but only because [Vector3] exists as a convenient data-structure to store 3 floating-point numbers. Therefore, applying affine operations on the rotation "vector" is not meaningful.
</member>
+ <member name="rotation_edit_mode" type="int" setter="set_rotation_edit_mode" getter="get_rotation_edit_mode" enum="Node3D.RotationEditMode" default="0">
+ Specify how rotation (and scale) will be presented in the editor.
+ </member>
+ <member name="rotation_order" type="int" setter="set_rotation_order" getter="get_rotation_order" enum="Node3D.RotationOrder" default="2">
+ Specify the axis rotation order of the [member rotation] property. The final orientation is constructed by rotating the Euler angles in the order specified by this property.
+ </member>
<member name="scale" type="Vector3" setter="set_scale" getter="get_scale" default="Vector3(1, 1, 1)">
Scale part of the local transformation.
</member>
@@ -311,5 +323,23 @@
<constant name="NOTIFICATION_VISIBILITY_CHANGED" value="43">
Node3D nodes receives this notification when their visibility changes.
</constant>
+ <constant name="ROTATION_EDIT_MODE_EULER" value="0" enum="RotationEditMode">
+ </constant>
+ <constant name="ROTATION_EDIT_MODE_QUATERNION" value="1" enum="RotationEditMode">
+ </constant>
+ <constant name="ROTATION_EDIT_MODE_BASIS" value="2" enum="RotationEditMode">
+ </constant>
+ <constant name="ROTATION_ORDER_XYZ" value="0" enum="RotationOrder">
+ </constant>
+ <constant name="ROTATION_ORDER_XZY" value="1" enum="RotationOrder">
+ </constant>
+ <constant name="ROTATION_ORDER_YXZ" value="2" enum="RotationOrder">
+ </constant>
+ <constant name="ROTATION_ORDER_YZX" value="3" enum="RotationOrder">
+ </constant>
+ <constant name="ROTATION_ORDER_ZXY" value="4" enum="RotationOrder">
+ </constant>
+ <constant name="ROTATION_ORDER_ZYX" value="5" enum="RotationOrder">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 656fa61af7..15cc7b9b65 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -57,7 +57,7 @@
<argument index="0" name="msec" type="int" />
<description>
Delays execution of the current thread by [code]msec[/code] milliseconds. [code]msec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] will do nothing and will print an error message.
- [b]Note:[/b] [method delay_msec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Yielding with [method SceneTree.create_timer] will delay the execution of code placed below the [code]yield[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s).
+ [b]Note:[/b] [method delay_msec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Awaiting with [method SceneTree.create_timer] will delay the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s).
[b]Note:[/b] When [method delay_msec] is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using [method delay_msec] as part of an [EditorPlugin] or [EditorScript], it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process).
</description>
</method>
@@ -66,7 +66,7 @@
<argument index="0" name="usec" type="int" />
<description>
Delays execution of the current thread by [code]usec[/code] microseconds. [code]usec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_usec] will do nothing and will print an error message.
- [b]Note:[/b] [method delay_usec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Yielding with [method SceneTree.create_timer] will delay the execution of code placed below the [code]yield[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s).
+ [b]Note:[/b] [method delay_usec] is a [i]blocking[/i] way to delay code execution. To delay code execution in a non-blocking way, see [method SceneTree.create_timer]. Awaiting with [method SceneTree.create_timer] will delay the execution of code placed below the [code]await[/code] without affecting the rest of the project (or editor, for [EditorPlugin]s and [EditorScript]s).
[b]Note:[/b] When [method delay_usec] is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using [method delay_usec] as part of an [EditorPlugin] or [EditorScript], it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process).
</description>
</method>
diff --git a/doc/classes/PointLight2D.xml b/doc/classes/PointLight2D.xml
index 9c13179056..ec809ed0a8 100644
--- a/doc/classes/PointLight2D.xml
+++ b/doc/classes/PointLight2D.xml
@@ -8,7 +8,7 @@
</tutorials>
<members>
<member name="height" type="float" setter="set_height" getter="get_height" default="0.0">
- The height of the light. Used with 2D normal mapping.
+ The height of the light. Used with 2D normal mapping. The units are in pixels, e.g. if the height is 100, then it will illuminate an object 100 pixels away at a 45° angle to the plane.
</member>
<member name="offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset" default="Vector2(0, 0)">
The offset of the light's [member texture].
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index eec06d6f82..c646380bee 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -221,11 +221,6 @@
The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files. The window title will be set to match the project name automatically on startup.
[b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information.
</member>
- <member name="application/config/project_data_dir_name" type="String" setter="" getter="" default="&quot;.godot&quot;">
- The project data directory is used for storing project-specific data (metadata, shader cache, etc.).
- [b]Note:[/b] Restart the application after changing this setting.
- [b]Note:[/b] Changing this value can help on platforms or with third-party tools where specific directory patterns are disallowed. Only modify this setting if you know that your environment requires it, as changing the default can impact compatibility with some external tools or plugins which expect the default [code].godot[/code] folder.
- </member>
<member name="application/config/project_settings_override" type="String" setter="" getter="" default="&quot;&quot;">
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information.
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
@@ -233,6 +228,12 @@
<member name="application/config/use_custom_user_dir" type="bool" setter="" getter="" default="false">
If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code].
</member>
+ <member name="application/config/use_hidden_project_data_directory" type="bool" setter="" getter="" default="true">
+ If [code]true[/code], the project will use a hidden directory ([code].godot[/code]) for storing project-specific data (metadata, shader cache, etc.).
+ If [code]false[/code], a non-hidden directory ([code]godot[/code]) will be used instead.
+ [b]Note:[/b] Restart the application after changing this setting.
+ [b]Note:[/b] Changing this value can help on platforms or with third-party tools where hidden directory patterns are disallowed. Only modify this setting if you know that your environment requires it, as changing the default can impact compatibility with some external tools or plugins which expect the default [code].godot[/code] folder.
+ </member>
<member name="application/config/windows_native_icon" type="String" setter="" getter="" default="&quot;&quot;">
Icon set in [code].ico[/code] format used on Windows to set the game's icon. This is done automatically on start by calling [method DisplayServer.set_native_icon].
</member>
@@ -1698,8 +1699,10 @@
<member name="rendering/shadows/directional_shadow/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/shadows/directional_shadow/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/shadows/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/directional_shadow/soft_shadow_quality" type="int" setter="" getter="" default="3">
Quality setting for shadows cast by [DirectionalLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
+ [b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
+ [b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply [i]constant[/i] shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/shadows/directional_shadow/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/shadows/directional_shadow/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
@@ -1724,8 +1727,10 @@
<member name="rendering/shadows/shadow_atlas/size.mobile" type="int" setter="" getter="" default="2048">
Lower-end override for [member rendering/shadows/shadow_atlas/size] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/shadows/shadows/soft_shadow_quality" type="int" setter="" getter="" default="2">
+ <member name="rendering/shadows/shadows/soft_shadow_quality" type="int" setter="" getter="" default="3">
Quality setting for shadows cast by [OmniLight3D]s and [SpotLight3D]s. Higher quality settings use more samples when reading from shadow maps and are thus slower. Low quality settings may result in shadows looking grainy.
+ [b]Note:[/b] The Soft Very Low setting will automatically multiply [i]constant[/i] shadow blur by 0.75x to reduce the amount of noise visible. This automatic blur change only affects the constant blur factor defined in [member Light3D.shadow_blur], not the variable blur performed by [DirectionalLight3D]s' [member Light3D.light_angular_distance].
+ [b]Note:[/b] The Soft High and Soft Ultra settings will automatically multiply shadow blur by 1.5× and 2× respectively to make better use of the increased sample count. This increased blur also improves stability of dynamic object shadows.
</member>
<member name="rendering/shadows/shadows/soft_shadow_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/shadows/shadows/soft_shadow_quality] on mobile devices, due to performance concerns or driver support.
@@ -1750,23 +1755,23 @@
</member>
<member name="rendering/textures/vram_compression/import_bptc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the Vulkan renderer.
- [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/project_data_dir_name]).
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_etc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
- [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/project_data_dir_name]).
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_etc2" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the Vulkan renderer.
- [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/project_data_dir_name]).
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_pvrtc" type="bool" setter="" getter="" default="false">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
- [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/project_data_dir_name]).
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/textures/vram_compression/import_s3tc" type="bool" setter="" getter="" default="true">
If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
- [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/project_data_dir_name]).
+ [b]Note:[/b] Changing this setting does [i]not[/i] impact textures that were already imported before. To make this setting apply to textures that were already imported, exit the editor, remove the [code].godot/imported/[/code] folder located inside the project folder then restart the editor (see [member application/config/use_hidden_project_data_directory]).
</member>
<member name="rendering/vulkan/descriptor_pools/max_descriptors_per_pool" type="int" setter="" getter="" default="64">
</member>
diff --git a/doc/classes/Quaternion.xml b/doc/classes/Quaternion.xml
index 7858ac732b..9c948ca21a 100644
--- a/doc/classes/Quaternion.xml
+++ b/doc/classes/Quaternion.xml
@@ -43,9 +43,8 @@
</method>
<method name="Quaternion" qualifiers="constructor">
<return type="Quaternion" />
- <argument index="0" name="euler" type="Vector3" />
+ <argument index="0" name="euler_yxz" type="Vector3" />
<description>
- Constructs a quaternion that will perform a rotation specified by Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), given in the vector format as (X angle, Y angle, Z angle).
</description>
</method>
<method name="Quaternion" qualifiers="constructor">
@@ -90,6 +89,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/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 6f19114c16..973f8cdb1e 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -3663,16 +3663,25 @@
Use 4 splits for shadow projection when using directional light.
</constant>
<constant name="SHADOW_QUALITY_HARD" value="0" enum="ShadowQuality">
+ Lowest shadow filtering quality (fastest). Soft shadows are not available with this quality setting, which means the [member Light3D.shadow_blur] property is ignored if [member Light3D.light_size] and [member Light3D.light_angular_distance] is [code]0.0[/code].
+ [b]Note:[/b] The variable shadow blur performed by [member Light3D.light_size] and [member Light3D.light_angular_distance] is still effective when using hard shadow filtering. In this case, [member Light3D.shadow_blur] [i]is[/i] taken into account. However, the results will not be blurred, instead the blur amount is treated as a maximum radius for the penumbra.
</constant>
- <constant name="SHADOW_QUALITY_SOFT_LOW" value="1" enum="ShadowQuality">
+ <constant name="SHADOW_QUALITY_SOFT_VERY_LOW" value="1" enum="ShadowQuality">
+ Very low shadow filtering quality (faster). When using this quality setting, [member Light3D.shadow_blur] is automatically multiplied by 0.75× to avoid introducing too much noise. This division only applies to lights whose [member Light3D.light_size] or [member Light3D.light_angular_distance] is [code]0.0[/code]).
</constant>
- <constant name="SHADOW_QUALITY_SOFT_MEDIUM" value="2" enum="ShadowQuality">
+ <constant name="SHADOW_QUALITY_SOFT_LOW" value="2" enum="ShadowQuality">
+ Low shadow filtering quality (fast).
</constant>
- <constant name="SHADOW_QUALITY_SOFT_HIGH" value="3" enum="ShadowQuality">
+ <constant name="SHADOW_QUALITY_SOFT_MEDIUM" value="3" enum="ShadowQuality">
+ Medium low shadow filtering quality (average).
</constant>
- <constant name="SHADOW_QUALITY_SOFT_ULTRA" value="4" enum="ShadowQuality">
+ <constant name="SHADOW_QUALITY_SOFT_HIGH" value="4" enum="ShadowQuality">
+ High low shadow filtering quality (slow). When using this quality setting, [member Light3D.shadow_blur] is automatically multiplied by 1.5× to better make use of the high sample count. This increased blur also improves the stability of dynamic object shadows. This multiplier only applies to lights whose [member Light3D.light_size] or [member Light3D.light_angular_distance] is [code]0.0[/code]).
</constant>
- <constant name="SHADOW_QUALITY_MAX" value="5" enum="ShadowQuality">
+ <constant name="SHADOW_QUALITY_SOFT_ULTRA" value="5" enum="ShadowQuality">
+ Highest low shadow filtering quality (slowest). When using this quality setting, [member Light3D.shadow_blur] is automatically multiplied by 2× to better make use of the high sample count. This increased blur also improves the stability of dynamic object shadows. This multiplier only applies to lights whose [member Light3D.light_size] or [member Light3D.light_angular_distance] is [code]0.0[/code]).
+ </constant>
+ <constant name="SHADOW_QUALITY_MAX" value="6" enum="ShadowQuality">
</constant>
<constant name="REFLECTION_PROBE_UPDATE_ONCE" value="0" enum="ReflectionProbeUpdateMode">
Reflection probe will update reflections once and then stop.
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 668f9af4a2..9337339f73 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -36,10 +36,10 @@
</description>
</method>
<method name="append_text">
- <return type="int" enum="Error" />
+ <return type="void" />
<argument index="0" name="bbcode" type="String" />
<description>
- Parses [code]bbcode[/code] and adds tags to the tag stack as needed. Returns the result of the parsing, [constant OK] if successful.
+ Parses [code]bbcode[/code] and adds tags to the tag stack as needed.
[b]Note:[/b] Using this method, you can't close a tag that was opened in a previous [method append_text] call. This is done to improve performance, especially when updating large RichTextLabels since rebuilding the whole BBCode every time would be slower. If you absolutely need to close a tag in a future method call, append the [member text] instead of using [method append_text].
</description>
</method>
@@ -130,10 +130,10 @@
</description>
</method>
<method name="parse_bbcode">
- <return type="int" enum="Error" />
+ <return type="void" />
<argument index="0" name="bbcode" type="String" />
<description>
- The assignment version of [method append_text]. Clears the tag stack and inserts the new content. Returns [constant OK] if parses [code]bbcode[/code] successfully.
+ The assignment version of [method append_text]. Clears the tag stack and inserts the new content.
</description>
</method>
<method name="parse_expressions_for_values">
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index ce7fd293d5..6d0ec44b69 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -66,7 +66,7 @@
[gdscript]
func some_function():
print("start")
- yield(get_tree().create_timer(1.0), "timeout")
+ await get_tree().create_timer(1.0).timeout
print("end")
[/gdscript]
[csharp]
diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml
index f97c5e42b5..b0509a322e 100644
--- a/doc/classes/SceneTreeTimer.xml
+++ b/doc/classes/SceneTreeTimer.xml
@@ -10,7 +10,7 @@
[gdscript]
func some_function():
print("Timer started.")
- yield(get_tree().create_timer(1.0), "timeout")
+ await get_tree().create_timer(1.0).timeout
print("Timer ended.")
[/gdscript]
[csharp]
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 10ce03c4b2..abb68e0d05 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -56,11 +56,11 @@
Converts a string containing a binary number into an integer. Binary strings can either be prefixed with [code]0b[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
[codeblocks]
[gdscript]
- print("0x101".bin_to_int()) # Prints "5".
+ print("0b101".bin_to_int()) # Prints "5".
print("101".bin_to_int()) # Prints "5".
[/gdscript]
[csharp]
- GD.Print("0x101".BinToInt()); // Prints "5".
+ GD.Print("0b101".BinToInt()); // Prints "5".
GD.Print("101".BinToInt()); // Prints "5".
[/csharp]
[/codeblocks]
diff --git a/doc/classes/Tabs.xml b/doc/classes/TabBar.xml
index ded4f0b32f..3ca124bb58 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/TabBar.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Tabs" inherits="Control" version="4.0">
+<class name="TabBar" inherits="Control" version="4.0">
<brief_description>
- Tabs control.
+ Tab bar control.
</brief_description>
<description>
Simple tabs control, similar to [TabContainer] but is only in charge of drawing tabs, not interacting with children.
@@ -114,7 +114,7 @@
<method name="get_tabs_rearrange_group" qualifiers="const">
<return type="int" />
<description>
- Returns the [Tabs]' rearrange group ID.
+ Returns the [TabBar]'s rearrange group ID.
</description>
</method>
<method name="move_tab">
@@ -192,7 +192,7 @@
<return type="void" />
<argument index="0" name="group_id" type="int" />
<description>
- Defines the rearrange group ID. Choose for each [Tabs] the same value to dragging tabs between [Tabs]. Enable drag with [member drag_to_rearrange_enabled].
+ Defines the rearrange group ID. Choose for each [TabBar] the same value to dragging tabs between [TabBar]. Enable drag with [member drag_to_rearrange_enabled].
</description>
</method>
</methods>
@@ -209,10 +209,10 @@
<member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled" default="true">
if [code]true[/code], the mouse's scroll wheel can be used to navigate the scroll view.
</member>
- <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign" default="1">
+ <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="TabBar.TabAlign" default="1">
The alignment of all tabs. See [enum TabAlign] for details.
</member>
- <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy" default="0">
+ <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="TabBar.CloseButtonDisplayPolicy" default="0">
Sets when the close button will appear on the tabs. See [enum CloseButtonDisplayPolicy] for details.
</member>
</members>
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index a3914b58df..ba3394b54a 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -41,6 +41,13 @@
Override this method to define what happens when the user performs a paste operation.
</description>
</method>
+ <method name="_paste_primary_clipboard" qualifiers="virtual">
+ <return type="void" />
+ <description>
+ Override this method to define what happens when the user performs a paste operation with middle mouse button.
+ [b]Note:[/b] This method is only implemented on Linux.
+ </description>
+ </method>
<method name="add_gutter">
<return type="void" />
<argument index="0" name="at" type="int" default="-1" />
@@ -937,6 +944,10 @@
<member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</member>
+ <member name="middle_mouse_paste_enabled" type="bool" setter="set_middle_mouse_paste_enabled" getter="is_middle_mouse_paste_enabled" default="true">
+ If [code]false[/code], using middle mouse button to paste clipboard will be disabled.
+ [b]Note:[/b] This method is only implemented on Linux.
+ </member>
<member name="minimap_draw" type="bool" setter="set_draw_minimap" getter="is_drawing_minimap" default="false">
If [code]true[/code], a minimap is shown, providing an outline of your source code.
</member>
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/doc/translations/Makefile b/doc/translations/Makefile
index ceee79ec95..ab08e107d0 100644
--- a/doc/translations/Makefile
+++ b/doc/translations/Makefile
@@ -21,3 +21,24 @@ merge:
check:
@for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done
+
+# Generate completion ratio from statistics string such as:
+# 2775 translated messages, 272 fuzzy translations, 151 untranslated messages.
+# First number can be 0, second and third numbers are only present if non-zero.
+include-list:
+ @list=""; \
+ threshold=0.10; \
+ for po in $(POFILES); do \
+ res=`msgfmt --statistics $$po -o /dev/null 2>&1 | sed 's/[^0-9,]*//g'`; \
+ complete=`cut -d',' -f1 <<< $$res`; \
+ fuzzy_or_untranslated=`cut -d',' -f2 <<< $$res`; \
+ untranslated_maybe=`cut -d',' -f3 <<< $$res`; \
+ if [ -z "$$fuzzy_or_untranslated" ]; then fuzzy_or_untranslated=0; fi; \
+ if [ -z "$$untranslated_maybe" ]; then untranslated_maybe=0; fi; \
+ incomplete=`expr $$fuzzy_or_untranslated + $$untranslated_maybe`; \
+ if `awk "BEGIN {exit !($$complete / ($$complete + $$incomplete) > $$threshold)}"`; then \
+ lang=`basename $$po .po`; \
+ list+="$$lang,"; \
+ fi; \
+ done; \
+ echo $$list;
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 8743135f89..e7ac447426 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -8913,6 +8913,8 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de
}
}
+ // Note: If adding new project settings here, also duplicate their definition in
+ // rendering_server.cpp for headless doctool.
staging_buffer_block_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256);
staging_buffer_block_size = MAX(4, staging_buffer_block_size);
staging_buffer_block_size *= 1024; //kb -> bytes
diff --git a/editor/SCsub b/editor/SCsub
index e8d417319a..6b18eeae93 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -5,7 +5,6 @@ Import("env")
env.editor_sources = []
import os
-import os.path
import glob
import editor_builders
@@ -59,7 +58,7 @@ if env["tools"]:
else:
docs += Glob(d + "/*.xml") # Custom.
- _make_doc_data_class_path(os.path.join(env.Dir("#").abspath, "editor"))
+ _make_doc_data_class_path(env.Dir("#editor").abspath)
docs = sorted(docs)
env.Depends("#editor/doc_data_compressed.gen.h", docs)
@@ -69,10 +68,17 @@ if env["tools"]:
env.Run(editor_builders.make_doc_header, "Generating documentation header."),
)
- path = env.Dir(".").abspath
+ # Editor interface and class reference translations incur a significant size
+ # cost for the editor binary (see godot-proposals#3421).
+ # To limit it, we only include translations with a high enough completion
+ # ratio (30% for the editor UI, 10% for the class reference).
+ # Generated with `make include-list` for each resource.
# Editor translations
- tlist = glob.glob(path + "/translations/*.po")
+ to_include = (
+ "ar,bg,bn,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,sv,th,tr,uk,vi,zh_CN,zh_TW"
+ ).split(",")
+ tlist = [env.Dir("#editor/translations").abspath + "/" + f + ".po" for f in to_include]
env.Depends("#editor/editor_translations.gen.h", tlist)
env.CommandNoCache(
"#editor/editor_translations.gen.h",
@@ -81,7 +87,8 @@ if env["tools"]:
)
# Documentation translations
- tlist = glob.glob(env.Dir("#doc").abspath + "/translations/*.po")
+ to_include = "es,fr,ja,zh_CN".split(",")
+ tlist = [env.Dir("#doc/translations").abspath + "/" + f + ".po" for f in to_include]
env.Depends("#editor/doc_translations.gen.h", tlist)
env.CommandNoCache(
"#editor/doc_translations.gen.h",
@@ -90,8 +97,8 @@ if env["tools"]:
)
# Fonts
- flist = glob.glob(path + "/../thirdparty/fonts/*.ttf")
- flist.extend(glob.glob(path + "/../thirdparty/fonts/*.otf"))
+ flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf")
+ flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf"))
flist.sort()
env.Depends("#editor/builtin_fonts.gen.h", flist)
env.CommandNoCache(
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/code_editor.h b/editor/code_editor.h
index 3c52a0c6e8..6e3bd88112 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -53,7 +53,6 @@ public:
void popup_find_line(CodeEdit *p_edit);
int get_line() const;
- void set_text_editor(CodeEdit *p_text_editor);
GotoLineDialog();
};
@@ -101,7 +100,6 @@ class FindReplaceBar : public HBoxContainer {
void _search_text_changed(const String &p_text);
void _search_text_submitted(const String &p_text);
void _replace_text_submitted(const String &p_text);
- void _update_size();
protected:
void _notification(int p_what);
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 9184ddcf39..976d718b8e 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -135,8 +135,6 @@ private:
Vector<Callable> undo_redo_callbacks;
Map<StringName, Callable> move_element_functions;
- void _cleanup_history();
-
Vector<EditedScene> edited_scene;
int current_edited_scene;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 767856f939..3d6b523733 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -2163,7 +2163,8 @@ Error EditorFileSystem::_resource_import(const String &p_path) {
}
bool EditorFileSystem::_should_skip_directory(const String &p_path) {
- if (p_path.begins_with(ProjectSettings::get_singleton()->get_project_data_path())) {
+ String project_data_path = ProjectSettings::get_singleton()->get_project_data_path();
+ if (p_path == project_data_path || p_path.begins_with(project_data_path + "/")) {
return true;
}
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_help.h b/editor/editor_help.h
index 7a45b1abc1..46605b6763 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -57,7 +57,6 @@ class FindBar : public HBoxContainer {
int results_count;
- void _show_search();
void _hide_bar();
void _search_text_changed(const String &p_text);
@@ -66,8 +65,6 @@ class FindBar : public HBoxContainer {
void _update_results_count();
void _update_matches_label();
- void _update_size();
-
protected:
void _notification(int p_what);
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 06af8566ff..124ea31302 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -96,8 +96,6 @@ private:
bool draw_top_bg;
void _ensure_popup();
- bool _is_property_different(const Variant &p_current, const Variant &p_orig);
- bool _get_instantiated_node_original_property(const StringName &p_prop, Variant &value);
void _focusable_focused(int p_index);
bool selectable;
@@ -281,8 +279,6 @@ public:
void unfold();
void fold();
- Object *get_edited_object();
-
EditorInspectorSection();
~EditorInspectorSection();
};
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index ffcb75ba2c..891705da98 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -59,8 +59,8 @@
#include "scene/gui/panel.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/split_container.h"
+#include "scene/gui/tab_bar.h"
#include "scene/gui/tab_container.h"
-#include "scene/gui/tabs.h"
#include "scene/gui/texture_progress_bar.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
@@ -658,7 +658,7 @@ void EditorNode::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
theme = create_custom_theme(theme_base->get_theme());
theme_base->set_theme(theme);
@@ -838,7 +838,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
}
if (res->get_import_path() != String()) {
- //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
+ // this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback
continue;
}
@@ -942,21 +942,21 @@ void EditorNode::_fs_changed() {
}
void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
- List<String> scenes; //will load later
+ List<String> scenes; // will load later
int current_tab = scene_tabs->get_current_tab();
for (int i = 0; i < p_resources.size(); i++) {
String file_type = ResourceLoader::get_resource_type(p_resources[i]);
if (file_type == "PackedScene") {
scenes.push_back(p_resources[i]);
- //reload later if needed, first go with normal resources
+ // reload later if needed, first go with normal resources
continue;
}
if (!ResourceCache::has(p_resources[i])) {
- continue; //not loaded, no need to reload
+ continue; // not loaded, no need to reload
}
- //reload normally
+ // reload normally
Resource *resource = ResourceCache::get(p_resources[i]);
if (resource) {
resource->reload_from_file();
@@ -1140,7 +1140,7 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d
ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN);
if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) {
- //current_option = -1;
+ // current_option = -1;
Vector<String> errors;
for (Set<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) {
errors.push_back(E->get());
@@ -1216,7 +1216,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
List<String> preferred;
for (const String &E : extensions) {
if (p_resource->is_class("Script") && (E == "tres" || E == "res")) {
- //this serves no purpose and confused people
+ // this serves no purpose and confused people
continue;
}
file->add_filter("*." + E + " ; " + E.to_upper());
@@ -1325,7 +1325,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
Error err = cf->load(path);
if (err != OK || !cf->has_section("editor_states")) {
- return; //must not exist
+ return; // must not exist
}
List<String> esl;
@@ -1349,7 +1349,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
return;
}
- scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it)
+ scene->set_meta("__editor_run_settings__", Variant()); // clear it (no point in keeping it)
scene->set_meta("__editor_plugin_states__", Variant());
String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg");
@@ -1392,10 +1392,10 @@ bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, i
if (p_res->get_path().is_resource_file()) {
if (changed || subchanged) {
- //save
+ // save
ResourceSaver::save(p_res->get_path(), p_res, flags);
}
- processed[p_res] = false; //because it's a file
+ processed[p_res] = false; // because it's a file
return false;
} else {
processed[p_res] = changed;
@@ -1493,7 +1493,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
_find_node_types(editor_data.get_edited_scene_root(), c2d, c3d);
save.step(TTR("Creating Thumbnail"), 1);
- //current view?
+ // current view?
Ref<Image> img;
// If neither 3D or 2D nodes are present, make a 1x1 black texture.
@@ -1546,12 +1546,12 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) {
}
img->convert(Image::FORMAT_RGB8);
- //save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
+ // save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5
String temp_path = EditorPaths::get_singleton()->get_cache_dir();
String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text();
cache_base = temp_path.plus_file("resthumb-" + cache_base);
- //does not have it, try to load a cached thumbnail
+ // does not have it, try to load a cached thumbnail
String file = cache_base + ".png";
@@ -1599,7 +1599,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso
if (res.is_null()) {
continue;
}
- if (res->get_path().is_resource_file()) { //not a subresource, continue
+ if (res->get_path().is_resource_file()) { // not a subresource, continue
continue;
}
if (_find_edited_resources(res, edited_resources)) {
@@ -1612,7 +1612,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso
}
int EditorNode::_save_external_resources() {
- //save external resources and its subresources if any was modified
+ // save external resources and its subresources if any was modified
int flg = 0;
if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) {
@@ -1628,7 +1628,7 @@ int EditorNode::_save_external_resources() {
if (!res->get_path().is_resource_file()) {
continue;
}
- //not only check if this resource is edited, check contained subresources too
+ // not only check if this resource is edited, check contained subresources too
if (_find_edited_resources(res, edited_subresources)) {
ResourceSaver::save(res->get_path(), res, flg);
saved++;
@@ -1837,7 +1837,7 @@ void EditorNode::_dialog_action(String p_file) {
case SETTINGS_PICK_MAIN_SCENE: {
ProjectSettings::get_singleton()->set("application/run/main_scene", p_file);
ProjectSettings::get_singleton()->save();
- //would be nice to show the project manager opened with the highlighted field..
+ // would be nice to show the project manager opened with the highlighted field..
if (pick_main_scene->has_meta("from_native") && (bool)pick_main_scene->get_meta("from_native")) {
run_native->resume_run_native();
@@ -1980,7 +1980,7 @@ void EditorNode::_dialog_action(String p_file) {
}
} break;
- default: { //save scene?
+ default: { // save scene?
if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) {
_save_scene_with_preview(p_file);
@@ -2141,7 +2141,7 @@ void EditorNode::_edit_current() {
bool is_resource = current_obj->is_class("Resource");
bool is_node = current_obj->is_class("Node");
- String editable_warning; //none by default
+ String editable_warning; // none by default
if (is_resource) {
Resource *current_res = Object::cast_to<Resource>(current_obj);
@@ -2243,7 +2243,7 @@ void EditorNode::_edit_current() {
for (; plugin_index < editor_table.size(); plugin_index++) {
if (editor_table[plugin_index] == main_plugin) {
if (!main_editor_buttons[plugin_index]->is_visible()) {
- main_plugin = nullptr; //if button is not visible, then no plugin active
+ main_plugin = nullptr; // if button is not visible, then no plugin active
}
break;
@@ -2329,7 +2329,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
if (run_filename == "") {
- //evidently, run the scene
+ // evidently, run the scene
if (!ensure_main_scene(false)) {
return;
}
@@ -2412,7 +2412,7 @@ void EditorNode::_android_build_source_selected(const String &p_file) {
export_template_manager->install_android_template_from_file(p_file);
}
void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
- if (!p_confirmed) { //this may be a hack..
+ if (!p_confirmed) { // this may be a hack..
current_option = (MenuOptions)p_option;
}
@@ -2981,7 +2981,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) {
void EditorNode::_exit_editor() {
exiting = true;
- resource_preview->stop(); //stop early to avoid crashes
+ resource_preview->stop(); // stop early to avoid crashes
_save_docks();
// Dim the editor window while it's quitting to make it clearer that it's busy
@@ -3087,7 +3087,7 @@ void EditorNode::_editor_select(int p_which) {
ERR_FAIL_INDEX(p_which, editor_table.size());
- if (!main_editor_buttons[p_which]->is_visible()) { //button hidden, no editor
+ if (!main_editor_buttons[p_which]->is_visible()) { // button hidden, no editor
return;
}
@@ -3229,7 +3229,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
if (!p_enabled) {
EditorPlugin *addon = plugin_addons[p_addon];
remove_editor_plugin(addon, p_config_changed);
- memdelete(addon); //bye
+ memdelete(addon); // bye
plugin_addons.erase(p_addon);
_update_addon_config();
return;
@@ -3321,10 +3321,10 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) {
void EditorNode::_remove_scene(int index, bool p_change_tab) {
if (editor_data.get_edited_scene() == index) {
- //Scene to remove is current scene
+ // Scene to remove is current scene
_remove_edited_scene(p_change_tab);
} else {
- //Scene to remove is not active scene
+ // Scene to remove is not active scene
editor_data.remove_scene(index);
}
}
@@ -3338,7 +3338,7 @@ void EditorNode::set_edited_scene(Node *p_scene) {
get_editor_data().set_edited_scene_root(p_scene);
if (Object::cast_to<Popup>(p_scene)) {
- Object::cast_to<Popup>(p_scene)->show(); //show popups
+ Object::cast_to<Popup>(p_scene)->show(); // show popups
}
scene_tree_dock->set_edited_scene(p_scene);
if (get_tree()) {
@@ -3374,7 +3374,7 @@ Dictionary EditorNode::_get_main_scene_state() {
void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
if (get_edited_scene() != p_for_scene && p_for_scene != nullptr) {
- return; //not for this scene
+ return; // not for this scene
}
changing_scene = false;
@@ -3389,7 +3389,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
if (p_state.has("editor_index")) {
int index = p_state["editor_index"];
- if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there
+ if (current < 2) { // if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there
if (index < 2 || !get_edited_scene()) {
_editor_select(index);
}
@@ -3398,7 +3398,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
if (get_edited_scene()) {
if (current < 2) {
- //use heuristic instead
+ // use heuristic instead
int n2d = 0, n3d = 0;
_find_node_types(get_edited_scene(), n2d, n3d);
if (n2d > n3d) {
@@ -3420,7 +3420,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
scene_tree_dock->set_filter(p_state["node_filter"]);
}
- //this should only happen at the very end
+ // this should only happen at the very end
EditorDebuggerNode::get_singleton()->update_live_edit_root();
ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene()));
@@ -3441,7 +3441,7 @@ void EditorNode::_clear_undo_history() {
}
void EditorNode::set_current_scene(int p_idx) {
- //Save the folding in case the scene gets reloaded.
+ // Save the folding in case the scene gets reloaded.
if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) {
editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
}
@@ -3469,7 +3469,7 @@ void EditorNode::set_current_scene(int p_idx) {
Node *new_scene = editor_data.get_edited_scene_root();
if (Object::cast_to<Popup>(new_scene)) {
- Object::cast_to<Popup>(new_scene)->show(); //show popups
+ Object::cast_to<Popup>(new_scene)->show(); // show popups
}
scene_tree_dock->set_edited_scene(new_scene);
@@ -3488,7 +3488,7 @@ void EditorNode::set_current_scene(int p_idx) {
_update_title();
- call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); //do after everything else is done setting up
+ call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // do after everything else is done setting up
}
bool EditorNode::is_scene_open(const String &p_path) {
@@ -3590,7 +3590,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
return ERR_FILE_MISSING_DEPENDENCIES;
}
- dependency_errors.erase(lpath); //at least not self path
+ dependency_errors.erase(lpath); // at least not self path
for (KeyValue<String, Set<String>> &E : dependency_errors) {
String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E.key) + "\n";
@@ -3601,7 +3601,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
}
if (ResourceCache::has(lpath)) {
- //used from somewhere else? no problem! update state and replace sdata
+ // used from somewhere else? no problem! update state and replace sdata
Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath)));
if (ps.is_valid()) {
ps->replace_state(sdata->get_state());
@@ -3610,7 +3610,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
}
} else {
- sdata->set_path(lpath, true); //take over path
+ sdata->set_path(lpath, true); // take over path
}
Node *new_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_MAIN);
@@ -4224,7 +4224,7 @@ void EditorNode::_dock_make_float() {
ERR_FAIL_COND(!dock);
const Size2i borders = Size2i(4, 4) * EDSCALE;
- Size2 dock_size = dock->get_size() + borders * 2; //remember size
+ Size2 dock_size = dock->get_size() + borders * 2; // remember size
Point2 dock_screen_pos = dock->get_global_position() + get_tree()->get_root()->get_position() - borders;
print_line("dock pos: " + dock->get_global_position() + " window pos: " + get_tree()->get_root()->get_position());
@@ -4464,7 +4464,7 @@ void EditorNode::_dock_select_draw() {
void EditorNode::_save_docks() {
if (waiting_for_first_scan) {
- return; //scanning, do not touch docks
+ return; // scanning, do not touch docks
}
Ref<ConfigFile> config;
config.instantiate();
@@ -4535,7 +4535,7 @@ void EditorNode::_load_docks() {
config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg"));
if (err != OK) {
- //no config
+ // no config
if (overridden_default_layout >= 0) {
_layout_menu_option(overridden_default_layout);
}
@@ -4648,7 +4648,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
for (int j = 0; j < names.size(); j++) {
String name = names[j];
- //find it, in a horribly inefficient way
+ // find it, in a horribly inefficient way
int atidx = -1;
Control *node = nullptr;
for (int k = 0; k < DOCK_SLOT_MAX; k++) {
@@ -4662,7 +4662,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
atidx = k;
break;
}
- if (atidx == -1) { //well, it's not anywhere
+ if (atidx == -1) { // well, it's not anywhere
continue;
}
@@ -4778,7 +4778,7 @@ bool EditorNode::has_scenes_in_session() {
}
bool EditorNode::ensure_main_scene(bool p_from_native) {
- pick_main_scene->set_meta("from_native", p_from_native); //whether from play button or native run
+ pick_main_scene->set_meta("from_native", p_from_native); // whether from play button or native run
String main_scene = GLOBAL_DEF("application/run/main_scene", "");
if (main_scene == "") {
@@ -4899,7 +4899,7 @@ void EditorNode::_update_layouts_menu() {
config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
- return; //no config
+ return; // no config
}
List<String> layouts;
@@ -4940,7 +4940,7 @@ void EditorNode::_layout_menu_option(int p_id) {
config.instantiate();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
if (err != OK) {
- return; //no config
+ return; // no config
}
_load_docks_from_config(config, editor_layouts->get_item_text(p_id));
@@ -5081,7 +5081,7 @@ void EditorNode::_scene_tab_changed(int p_tab) {
bool unsaved = (saved_version != editor_data.get_undo_redo().get_version());
if (p_tab == editor_data.get_edited_scene()) {
- return; //pointless
+ return; // pointless
}
uint64_t next_scene_version = editor_data.get_scene_version(p_tab);
@@ -5284,11 +5284,11 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
Ref<Texture2D> preview;
{
- //todo make proper previews
+ // todo make proper previews
Ref<ImageTexture> texture = gui_base->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
Ref<Image> img = texture->get_image();
img = img->duplicate();
- img->resize(48, 48); //meh
+ img->resize(48, 48); // meh
Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture));
resized_pic->create_from_image(img);
preview = resized_pic;
@@ -5306,7 +5306,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
drag_control->add_child(label);
- p_from->set_drag_preview(drag_control); //wait until it enters scene
+ p_from->set_drag_preview(drag_control); // wait until it enters scene
label->set_position(Point2((preview->get_width() - label->get_minimum_size().width) / 2, preview->get_height()));
@@ -5360,7 +5360,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *
}
vbox->add_child(label);
}
- p_from->set_drag_preview(vbox); //wait until it enters scene
+ p_from->set_drag_preview(vbox); // wait until it enters scene
Dictionary drag_data;
drag_data["type"] = has_folder ? "files_and_dirs" : "files";
@@ -5477,7 +5477,7 @@ void EditorNode::reload_scene(const String &p_path) {
if (scene_idx == -1) {
if (get_edited_scene()) {
- //scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
+ // scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
editor_data.get_undo_redo().clear_history();
}
return;
@@ -5488,17 +5488,17 @@ void EditorNode::reload_scene(const String &p_path) {
_set_scene_metadata(p_path);
}
- //remove scene
+ // remove scene
_remove_scene(scene_idx, false);
- //reload scene
+ // reload scene
load_scene(p_path, true, false, true, true);
- //adjust index so tab is back a the previous position
+ // adjust index so tab is back a the previous position
editor_data.move_edited_scene_to_index(scene_idx);
get_undo_redo()->clear_history();
- //recover the tab
+ // recover the tab
scene_tabs->set_current_tab(current_tab);
}
@@ -5598,7 +5598,7 @@ void EditorNode::_update_video_driver_color() {
void EditorNode::_video_driver_selected(int p_which) {
String driver = video_driver->get_item_metadata(p_which);
- String current = ""; //OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
+ String current = ""; // OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver());
if (driver == current) {
return;
@@ -5787,9 +5787,9 @@ EditorNode::EditorNode() {
PhysicsServer2D::get_singleton()->set_active(false); // no physics by default if editor
ScriptServer::set_scripting_enabled(false); // no scripting by default if editor
- EditorHelp::generate_doc(); //before any editor classes are created
+ EditorHelp::generate_doc(); // before any editor classes are created
SceneState::set_disable_placeholders(true);
- ResourceLoader::clear_translation_remaps(); //no remaps using during editor
+ ResourceLoader::clear_translation_remaps(); // no remaps using during editor
ResourceLoader::clear_path_remaps();
Input *id = Input::get_singleton();
@@ -5803,8 +5803,8 @@ EditorNode::EditorNode() {
}
if (!found_touchscreen && Input::get_singleton()) {
- //only if no touchscreen ui hint, set emulation
- id->set_emulate_touch_from_mouse(false); //just disable just in case
+ // only if no touchscreen ui hint, set emulation
+ id->set_emulate_touch_from_mouse(false); // just disable just in case
}
DisplayServer::get_singleton()->cursor_set_custom_image(RES());
}
@@ -5871,7 +5871,7 @@ EditorNode::EditorNode() {
ResourceLoader::set_error_notify_func(this, _load_error_notify);
ResourceLoader::set_dependency_error_notify_func(this, _dependency_error_report);
- { //register importers at the beginning, so dialogs are created with the right extensions
+ { // register importers at the beginning, so dialogs are created with the right extensions
Ref<ResourceImporterTexture> import_texture;
import_texture.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_texture);
@@ -5974,7 +5974,7 @@ EditorNode::EditorNode() {
EditorFileSystem *efs = memnew(EditorFileSystem);
add_child(efs);
- //used for previews
+ // used for previews
FileDialog::get_icon_func = _file_dialog_get_icon;
FileDialog::register_func = _file_dialog_register;
FileDialog::unregister_func = _file_dialog_unregister;
@@ -5993,7 +5993,7 @@ EditorNode::EditorNode() {
ClassDB::set_class_enabled("RootMotionView", true);
- //defs here, use EDITOR_GET in logic
+ // defs here, use EDITOR_GET in logic
EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false);
EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true);
EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50);
@@ -6217,13 +6217,13 @@ EditorNode::EditorNode() {
tab_preview->set_position(Point2(2, 2) * EDSCALE);
tab_preview_panel->add_child(tab_preview);
- scene_tabs = memnew(Tabs);
+ scene_tabs = memnew(TabBar);
scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles")));
scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles")));
scene_tabs->set_select_with_rmb(true);
scene_tabs->add_tab("unsaved");
- scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_tab_align(TabBar::ALIGN_LEFT);
+ scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
@@ -6924,7 +6924,7 @@ EditorNode::EditorNode() {
EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor();
- ScriptTextEditor::register_editor(); //register one for text scripts
+ ScriptTextEditor::register_editor(); // register one for text scripts
TextEditor::register_editor();
if (StreamPeerSSL::is_available()) {
@@ -6933,12 +6933,12 @@ EditorNode::EditorNode() {
WARN_PRINT("Asset Library not available, as it requires SSL to work.");
}
- //add interface before adding plugins
+ // add interface before adding plugins
editor_interface = memnew(EditorInterface);
add_child(editor_interface);
- //more visually meaningful to have this later
+ // more visually meaningful to have this later
raise_bottom_panel_item(AnimationPlayerEditor::get_singleton());
add_editor_plugin(VersionControlEditorPlugin::get_singleton());
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 5c89823ad8..c64bcc0460 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -85,7 +85,7 @@ class ProjectSettingsEditor;
class RunSettingsDialog;
class ScriptCreateDialog;
class TabContainer;
-class Tabs;
+class TabBar;
class TextureProgressBar;
class Button;
class VSplitContainer;
@@ -216,7 +216,7 @@ private:
TOOL_MENU_BASE = 1000
};
- SubViewport *scene_root; //root of the scene being edited
+ SubViewport *scene_root; // root of the scene being edited
PanelContainer *scene_root_parent;
Control *theme_base;
@@ -250,7 +250,7 @@ private:
// Main tabs
- Tabs *scene_tabs;
+ TabBar *scene_tabs;
PopupMenu *scene_tabs_context_menu;
Panel *tab_preview_panel;
TextureRect *tab_preview;
@@ -324,7 +324,7 @@ private:
EditorSettingsDialog *settings_config_dialog;
ProjectSettingsEditor *project_settings;
- bool settings_changed = true; //make it update settings on first frame
+ bool settings_changed = true; // make it update settings on first frame
void _update_from_settings();
PopupMenu *vcs_actions_menu;
@@ -520,9 +520,6 @@ private:
void _run(bool p_current = false, const String &p_custom = "");
void _run_native(const Ref<EditorExportPreset> &p_preset);
- void _save_optimized();
- void _import_action(const String &p_action);
- void _import(const String &p_file);
void _add_to_recent_scenes(const String &p_scene);
void _update_recent_scenes();
void _open_recent_scene(int p_idx);
@@ -560,7 +557,6 @@ private:
static void _editor_file_dialog_register(EditorFileDialog *p_dialog);
static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog);
- void _cleanup_scene();
void _remove_edited_scene(bool p_change_tab = true);
void _remove_scene(int index, bool p_change_tab = true);
bool _find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags);
@@ -658,8 +654,6 @@ private:
static int build_callback_count;
static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS];
- void _license_tree_selected();
-
void _update_update_spinner();
Vector<Ref<EditorResourceConversionPlugin>> resource_conversion_plugins;
@@ -775,10 +769,9 @@ public:
Node *get_edited_scene() { return editor_data.get_edited_scene_root(); }
- SubViewport *get_scene_root() { return scene_root; } //root of the scene being edited
+ SubViewport *get_scene_root() { return scene_root; } // root of the scene being edited
void fix_dependencies(const String &p_for_file);
- void clear_scene() { _cleanup_scene(); }
int new_scene();
Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_clear_errors = true, bool p_force_open_imported = false, bool p_silent_change_tab = false);
Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false);
@@ -851,8 +844,6 @@ public:
bool is_scene_in_use(const String &p_path);
- void scan_import_changes();
-
void save_layout();
void open_export_template_manager();
@@ -894,7 +885,6 @@ public:
EditorNode();
~EditorNode();
- void get_singleton(const char *arg1, bool arg2);
void add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin);
void remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin);
diff --git a/editor/editor_path.h b/editor/editor_path.h
index cabfa931d6..07f8b7244e 100644
--- a/editor/editor_path.h
+++ b/editor/editor_path.h
@@ -47,7 +47,6 @@ class EditorPath : public Button {
PopupMenu *sub_objects_menu;
Vector<ObjectID> objects;
- EditorPath();
void _show_popup();
void _id_pressed(int p_idx);
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/editor_themes.cpp b/editor/editor_themes.cpp
index 134f2ce202..fdcc0438ae 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -403,7 +403,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
float prev_icon_saturation = theme->has_color("icon_saturation", "Editor") ? theme->get_color("icon_saturation", "Editor").r : 1.0;
- theme->set_color("icon_saturation", "Editor", Color(icon_saturation, icon_saturation, icon_saturation)); //can't save single float in theme, so using color
+ theme->set_color("icon_saturation", "Editor", Color(icon_saturation, icon_saturation, icon_saturation)); // can't save single float in theme, so using color
theme->set_color("accent_color", "Editor", accent_color);
theme->set_color("highlight_color", "Editor", highlight_color);
theme->set_color("disabled_highlight_color", "Editor", disabled_highlight_color);
@@ -548,7 +548,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size);
- // Tabs
+ // TabBar
Ref<StyleBoxFlat> style_tab_selected = style_widget->duplicate();
@@ -949,33 +949,33 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE);
theme->set_constant("line_separation", "ItemList", 3 * EDSCALE);
- // Tabs & TabContainer
+ // TabBar & TabContainer
theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected);
theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected);
theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled);
- theme->set_stylebox("tab_selected", "Tabs", style_tab_selected);
- theme->set_stylebox("tab_unselected", "Tabs", style_tab_unselected);
- theme->set_stylebox("tab_disabled", "Tabs", style_tab_disabled);
+ theme->set_stylebox("tab_selected", "TabBar", style_tab_selected);
+ theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected);
+ theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled);
theme->set_color("font_selected_color", "TabContainer", font_color);
theme->set_color("font_unselected_color", "TabContainer", font_disabled_color);
- theme->set_color("font_selected_color", "Tabs", font_color);
- theme->set_color("font_unselected_color", "Tabs", font_disabled_color);
+ theme->set_color("font_selected_color", "TabBar", font_color);
+ theme->set_color("font_unselected_color", "TabBar", font_disabled_color);
theme->set_icon("menu", "TabContainer", theme->get_icon("GuiTabMenu", "EditorIcons"));
theme->set_icon("menu_highlight", "TabContainer", theme->get_icon("GuiTabMenuHl", "EditorIcons"));
theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected);
theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected);
- theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons"));
- theme->set_stylebox("close_bg_pressed", "Tabs", style_menu);
- theme->set_stylebox("close_bg_highlight", "Tabs", style_menu);
+ theme->set_icon("close", "TabBar", theme->get_icon("GuiClose", "EditorIcons"));
+ theme->set_stylebox("close_bg_pressed", "TabBar", style_menu);
+ theme->set_stylebox("close_bg_highlight", "TabBar", style_menu);
theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
- theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
- theme->set_icon("decrement", "Tabs", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
- theme->set_icon("increment_highlight", "Tabs", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons"));
- theme->set_icon("decrement_highlight", "Tabs", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons"));
+ theme->set_icon("increment", "TabBar", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
+ theme->set_icon("decrement", "TabBar", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+ theme->set_icon("increment_highlight", "TabBar", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons"));
+ theme->set_icon("decrement_highlight", "TabBar", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons"));
theme->set_icon("increment_highlight", "TabContainer", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons"));
theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons"));
- theme->set_constant("hseparation", "Tabs", 4 * EDSCALE);
+ theme->set_constant("hseparation", "TabBar", 4 * EDSCALE);
// Content of each tab
Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 1d1976d7e5..cdf0f6e391 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -688,9 +688,11 @@ void FileSystemDock::_sort_file_info_list(List<FileSystemDock::FileInfo> &r_file
r_file_list.reverse();
break;
case FILE_SORT_NAME_REVERSE:
+ r_file_list.sort();
r_file_list.reverse();
break;
default: // FILE_SORT_NAME
+ r_file_list.sort();
break;
}
}
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 73bdd685b7..7c3851b94f 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -205,8 +205,6 @@ private:
void _set_file_display(bool p_active);
void _fs_changed();
- void _tree_toggle_collapsed();
-
void _select_file(const String &p_path, bool p_select_in_favorites = false);
void _tree_activate_file();
void _file_list_activate_file(int p_idx);
@@ -228,8 +226,6 @@ private:
void _file_removed(String p_file);
void _folder_removed(String p_folder);
- void _files_moved(String p_old_file, String p_new_file);
- void _folder_moved(String p_old_folder, String p_new_folder);
void _resource_created();
void _make_dir_confirm();
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index b61f6e12eb..283496c0f1 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -235,7 +235,7 @@ void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) {
// Ignore special dirs (such as .git and project data directory)
String project_data_dir_name = ProjectSettings::get_singleton()->get_project_data_dir_name();
- if (file.begins_with(".") || file.begins_with(project_data_dir_name)) {
+ if (file.begins_with(".") || file == project_data_dir_name) {
continue;
}
if (dir->current_is_hidden()) {
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 113306fc8a..f01c7f50f7 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -204,7 +204,8 @@ void GroupDialog::_add_group(String p_name) {
TreeItem *new_group = groups->create_item(groups_root);
new_group->set_text(0, name);
- new_group->add_button(0, groups->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0);
+ new_group->add_button(0, groups->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), DELETE_GROUP);
+ new_group->add_button(0, groups->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), COPY_GROUP);
new_group->set_editable(0, true);
new_group->select(0);
groups->ensure_cursor_is_visible();
@@ -297,43 +298,50 @@ void GroupDialog::_load_groups(Node *p_current) {
}
}
-void GroupDialog::_delete_group_pressed(Object *p_item, int p_column, int p_id) {
+void GroupDialog::_modify_group_pressed(Object *p_item, int p_column, int p_id) {
TreeItem *ti = Object::cast_to<TreeItem>(p_item);
if (!ti) {
return;
}
- String name = ti->get_text(0);
+ switch (p_id) {
+ case DELETE_GROUP: {
+ String name = ti->get_text(0);
- undo_redo->create_action(TTR("Delete Group"));
+ undo_redo->create_action(TTR("Delete Group"));
- List<Node *> nodes;
- scene_tree->get_nodes_in_group(name, &nodes);
- bool removed_all = true;
- for (Node *E : nodes) {
- if (_can_edit(E, name)) {
- undo_redo->add_do_method(E, "remove_from_group", name);
- undo_redo->add_undo_method(E, "add_to_group", name, true);
- } else {
- removed_all = false;
- }
- }
+ List<Node *> nodes;
+ scene_tree->get_nodes_in_group(name, &nodes);
+ bool removed_all = true;
+ for (Node *E : nodes) {
+ if (_can_edit(E, name)) {
+ undo_redo->add_do_method(E, "remove_from_group", name);
+ undo_redo->add_undo_method(E, "add_to_group", name, true);
+ } else {
+ removed_all = false;
+ }
+ }
- if (removed_all) {
- undo_redo->add_do_method(this, "_delete_group_item", name);
- undo_redo->add_undo_method(this, "_add_group", name);
- }
+ if (removed_all) {
+ undo_redo->add_do_method(this, "_delete_group_item", name);
+ undo_redo->add_undo_method(this, "_add_group", name);
+ }
- undo_redo->add_do_method(this, "_group_selected");
- undo_redo->add_undo_method(this, "_group_selected");
- undo_redo->add_do_method(this, "emit_signal", "group_edited");
- undo_redo->add_undo_method(this, "emit_signal", "group_edited");
+ undo_redo->add_do_method(this, "_group_selected");
+ undo_redo->add_undo_method(this, "_group_selected");
+ undo_redo->add_do_method(this, "emit_signal", "group_edited");
+ undo_redo->add_undo_method(this, "emit_signal", "group_edited");
- // To force redraw of scene tree.
- undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
- undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
+ // To force redraw of scene tree.
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
- undo_redo->commit_action();
+ undo_redo->commit_action();
+ } break;
+ case COPY_GROUP: {
+ DisplayServer::get_singleton()->clipboard_set(ti->get_text(p_column));
+ } break;
+ }
}
void GroupDialog::_delete_group_item(const String &p_name) {
@@ -437,7 +445,7 @@ GroupDialog::GroupDialog() {
groups->set_v_size_flags(Control::SIZE_EXPAND_FILL);
groups->add_theme_constant_override("draw_guides", 1);
groups->connect("item_selected", callable_mp(this, &GroupDialog::_group_selected));
- groups->connect("button_pressed", callable_mp(this, &GroupDialog::_delete_group_pressed));
+ groups->connect("button_pressed", callable_mp(this, &GroupDialog::_modify_group_pressed));
groups->connect("item_edited", callable_mp(this, &GroupDialog::_group_renamed));
HBoxContainer *chbc = memnew(HBoxContainer);
@@ -582,7 +590,7 @@ void GroupsEditor::_add_group(const String &p_group) {
group_name->clear();
}
-void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) {
+void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id) {
if (!node) {
return;
}
@@ -591,21 +599,26 @@ void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) {
if (!ti) {
return;
}
+ switch (p_id) {
+ case DELETE_GROUP: {
+ String name = ti->get_text(0);
+ undo_redo->create_action(TTR("Remove from Group"));
- String name = ti->get_text(0);
-
- undo_redo->create_action(TTR("Remove from Group"));
-
- undo_redo->add_do_method(node, "remove_from_group", name);
- undo_redo->add_undo_method(node, "add_to_group", name, true);
- undo_redo->add_do_method(this, "update_tree");
- undo_redo->add_undo_method(this, "update_tree");
+ undo_redo->add_do_method(node, "remove_from_group", name);
+ undo_redo->add_undo_method(node, "add_to_group", name, true);
+ undo_redo->add_do_method(this, "update_tree");
+ undo_redo->add_undo_method(this, "update_tree");
- // To force redraw of scene tree.
- undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
- undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
+ // To force redraw of scene tree.
+ undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
+ undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree");
- undo_redo->commit_action();
+ undo_redo->commit_action();
+ } break;
+ case COPY_GROUP: {
+ DisplayServer::get_singleton()->clipboard_set(ti->get_text(p_column));
+ } break;
+ }
}
struct _GroupInfoComparator {
@@ -653,7 +666,8 @@ void GroupsEditor::update_tree() {
TreeItem *item = tree->create_item(root);
item->set_text(0, gi.name);
if (can_be_deleted) {
- item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0);
+ item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), DELETE_GROUP);
+ item->add_button(0, get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), COPY_GROUP);
} else {
item->set_selectable(0, false);
}
@@ -706,7 +720,7 @@ GroupsEditor::GroupsEditor() {
tree->set_hide_root(true);
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbc->add_child(tree);
- tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_remove_group));
+ tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_modify_group));
tree->add_theme_constant_override("draw_guides", 1);
add_theme_constant_override("separation", 3 * EDSCALE);
}
diff --git a/editor/groups_editor.h b/editor/groups_editor.h
index 69f746801f..f0a5b4a794 100644
--- a/editor/groups_editor.h
+++ b/editor/groups_editor.h
@@ -82,7 +82,7 @@ class GroupDialog : public AcceptDialog {
void _rename_group_item(const String &p_old_name, const String &p_new_name);
void _add_group(String p_name);
- void _delete_group_pressed(Object *p_item, int p_column, int p_id);
+ void _modify_group_pressed(Object *p_item, int p_column, int p_id);
void _delete_group_item(const String &p_name);
bool _can_edit(Node *p_node, String p_group);
@@ -95,6 +95,11 @@ protected:
static void _bind_methods();
public:
+ enum ModifyButton {
+ DELETE_GROUP,
+ COPY_GROUP,
+ };
+
void edit();
void set_undo_redo(UndoRedo *p_undoredo) { undo_redo = p_undoredo; }
@@ -116,8 +121,7 @@ class GroupsEditor : public VBoxContainer {
void update_tree();
void _add_group(const String &p_group = "");
- void _remove_group(Object *p_item, int p_column, int p_id);
- void _close();
+ void _modify_group(Object *p_item, int p_column, int p_id);
void _show_group_dialog();
@@ -125,6 +129,11 @@ protected:
static void _bind_methods();
public:
+ enum ModifyButton {
+ DELETE_GROUP,
+ COPY_GROUP,
+ };
+
void set_undo_redo(UndoRedo *p_undoredo) { undo_redo = p_undoredo; }
void set_current(Node *p_node);
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/icons/Tabs.svg b/editor/icons/TabBar.svg
index e20a1a0131..e20a1a0131 100644
--- a/editor/icons/Tabs.svg
+++ b/editor/icons/TabBar.svg
diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h
index 86e9c5bde8..7d8fb3cac5 100644
--- a/editor/import/resource_importer_layered_texture.h
+++ b/editor/import/resource_importer_layered_texture.h
@@ -91,8 +91,6 @@ public:
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;
- void update_imports();
-
virtual bool are_import_settings_valid(const String &p_path) const override;
virtual String get_import_settings_string() const override;
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/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index 4f9adfff25..5fea8b75d6 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -106,7 +106,6 @@ protected:
void _wip_changed();
void _wip_close();
void _wip_cancel();
- bool _delete_point(const Vector2 &p_gpoint);
void _notification(int p_what);
void _node_removed(Node *p_node);
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index fe98a91ab3..503e066894 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -109,8 +109,6 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
void _edit_point_pos(double);
void _open_editor();
- void _goto_parent();
-
EditorFileDialog *open_file;
Ref<AnimationNode> file_loaded;
void _file_opened(const String &p_file);
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index eb8db2eaba..26bcff891d 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -187,7 +187,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _scale_changed(const String &p_scale);
void _save_animation(String p_file);
void _load_animations(Vector<String> p_files);
- void _seek_frame_changed(const String &p_frame);
void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false);
void _blend_editor_next_changed(const int p_idx);
@@ -217,7 +216,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _pin_pressed();
- AnimationPlayerEditor();
~AnimationPlayerEditor();
protected:
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 286546f962..5fbf2833b2 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -285,7 +285,6 @@ class EditorAssetLibrary : public PanelContainer {
void _search_text_submitted(const String &p_text = "");
void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = "");
void _http_request_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
- void _http_download_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data);
void _filter_debounce_timer_timeout();
void _repository_changed(int p_repository_id);
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/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 1965efbf30..286771ee08 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -421,8 +421,6 @@ private:
CanvasItem *ref_item;
- void _add_canvas_item(CanvasItem *p_canvas_item);
-
void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false);
void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false);
void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false);
@@ -434,7 +432,6 @@ private:
bool updating_scroll;
void _update_scroll(real_t);
void _update_scrollbars();
- void _append_canvas_item(CanvasItem *p_item);
void _snap_changed();
void _selection_result_pressed(int);
void _selection_menu_hide();
@@ -519,7 +516,6 @@ private:
const Node *p_current);
void _set_anchors_preset(Control::LayoutPreset p_preset);
- void _set_offsets_preset(Control::LayoutPreset p_preset);
void _set_anchors_and_offsets_preset(Control::LayoutPreset p_preset);
void _set_anchors_and_offsets_to_keep_ratio();
@@ -551,15 +547,9 @@ protected:
void _notification(int p_what);
static void _bind_methods();
- void end_drag();
- void box_selection_start(Point2 &click);
- bool box_selection_end();
HBoxContainer *get_panel_hb() { return hb; }
- template <class P, class C>
- void space_selected_items();
-
static CanvasItemEditor *singleton;
public:
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 0096152cfe..af58d8bbdc 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);
@@ -3213,7 +3253,7 @@ void Node3DEditorViewport::_menu_option(int p_option) {
continue;
}
- undo_redo->add_do_method(sp, "set_rotation", camera_transform.basis.get_rotation());
+ undo_redo->add_do_method(sp, "set_rotation", camera_transform.basis.get_euler_normalized());
undo_redo->add_undo_method(sp, "set_rotation", sp->get_rotation());
}
undo_redo->commit_action();
@@ -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 2d5aeaa981..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();
@@ -677,8 +681,6 @@ private:
void _register_all_gizmos();
- Node3DEditor();
-
void _selection_changed();
void _refresh_menu_icons();
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index 04ab458eb5..943765d4e0 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -59,7 +59,6 @@ class ResourcePreloaderEditor : public PanelContainer {
ResourcePreloader *preloader;
void _load_pressed();
- void _load_scene_pressed();
void _files_load_request(const Vector<String> &p_paths);
void _paste_pressed();
void _remove_resource(const String &p_to_remove);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 8caebc1c8c..2b0bdfd109 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -371,14 +371,11 @@ class ScriptEditor : public PanelContainer {
bool use_space_indentation;
bool convert_indent_on_save;
- void _trim_trailing_whitespace(TextEdit *tx);
-
void _goto_script_line2(int p_line);
void _goto_script_line(REF p_script, int p_line);
void _set_execution(REF p_script, int p_line);
void _clear_execution(REF p_script);
void _breaked(bool p_breaked, bool p_can_debug);
- void _update_window_menu();
void _script_created(Ref<Script> p_script);
void _set_breakpoint(REF p_scrpt, int p_line, bool p_enabled);
void _clear_breakpoints();
@@ -430,7 +427,6 @@ class ScriptEditor : public PanelContainer {
void _make_script_list_context_menu();
void _help_search(String p_text);
- void _help_index(String p_text);
void _history_forward();
void _history_back();
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/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 5e3b2fb8c1..9732384000 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -100,7 +100,6 @@ class SpriteFramesEditor : public HSplitContainer {
float min_sheet_zoom;
void _load_pressed();
- void _load_scene_pressed();
void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
void _copy_pressed();
void _paste_pressed();
@@ -128,7 +127,6 @@ class SpriteFramesEditor : public HSplitContainer {
UndoRedo *undo_redo;
- bool _is_drop_valid(const Dictionary &p_drag_data, const Dictionary &p_item_data) const;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 19e1b40a0d..127219546d 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -3204,7 +3204,7 @@ void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const Stri
preview_tabs->add_tab(p_preview_name, p_icon);
preview_tabs_content->add_child(p_preview_tab);
- preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("close"), SNAME("Tabs")));
+ preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("close"), SNAME("TabBar")));
p_preview_tab->connect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked));
preview_tabs->set_current_tab(preview_tabs->get_tab_count() - 1);
@@ -3328,8 +3328,8 @@ ThemeEditor::ThemeEditor() {
preview_tabs_content->set_draw_behind_parent(true);
preview_tabs_vb->add_child(preview_tabs_content);
- preview_tabs = memnew(Tabs);
- preview_tabs->set_tab_align(Tabs::ALIGN_LEFT);
+ preview_tabs = memnew(TabBar);
+ preview_tabs->set_tab_align(TabBar::ALIGN_LEFT);
preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
preview_tabbar_hb->add_child(preview_tabs);
preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab));
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 5b0357e3f8..b6becbb1c7 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -34,7 +34,7 @@
#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/scroll_container.h"
-#include "scene/gui/tabs.h"
+#include "scene/gui/tab_bar.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/theme.h"
#include "theme_editor_preview.h"
@@ -347,7 +347,6 @@ class ThemeTypeEditor : public MarginContainer {
void _update_type_items();
void _list_type_selected(int p_index);
- void _select_type(String p_type_name);
void _add_type_button_cbk();
void _add_default_type_items();
@@ -391,7 +390,7 @@ class ThemeEditor : public VBoxContainer {
Ref<Theme> theme;
- Tabs *preview_tabs;
+ TabBar *preview_tabs;
PanelContainer *preview_tabs_content;
Button *add_preview_button;
EditorFileDialog *preview_scene_dialog;
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/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index b24f667914..5b7ec6c8db 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -3435,8 +3435,8 @@ TileMapEditor::TileMapEditor() {
tile_map_editor_plugins.push_back(memnew(TileMapEditorTilesPlugin));
tile_map_editor_plugins.push_back(memnew(TileMapEditorTerrainsPlugin));
- // Tabs.
- tabs_bar = memnew(Tabs);
+ // TabBar.
+ tabs_bar = memnew(TabBar);
tabs_bar->set_clip_tabs(false);
for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) {
Vector<TileMapEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs();
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index e3ac568b86..0513a7b365 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -38,7 +38,7 @@
#include "editor/editor_node.h"
#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
-#include "scene/gui/tabs.h"
+#include "scene/gui/tab_bar.h"
class TileMapEditorPlugin : public Object {
public:
@@ -301,7 +301,7 @@ private:
// Bottom panel.
Label *missing_tileset_label;
- Tabs *tabs_bar;
+ TabBar *tabs_bar;
LocalVector<TileMapEditorPlugin::TabData> tabs_data;
LocalVector<TileMapEditorPlugin *> tabs_plugins;
void _update_bottom_panel();
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index f2ee0c24da..0fbb9a98c7 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -642,8 +642,8 @@ TileSetEditor::TileSetEditor() {
set_process_internal(true);
- // Tabs.
- tabs_bar = memnew(Tabs);
+ // TabBar.
+ tabs_bar = memnew(TabBar);
tabs_bar->set_clip_tabs(false);
tabs_bar->add_tab(TTR("Tiles"));
tabs_bar->add_tab(TTR("Patterns"));
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index c9c7a3bb73..cda38760cf 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -48,9 +48,9 @@ private:
bool tile_set_changed_needs_update = false;
HSplitContainer *split_container;
- // Tabs.
+ // TabBar.
HBoxContainer *tile_set_toolbar;
- Tabs *tabs_bar;
+ TabBar *tabs_bar;
// Tiles.
Label *no_source_selected_label;
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 0a067dfc17..09ca1f7608 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "visual_shader_editor_plugin.h"
#include "core/config/project_settings.h"
+#include "core/core_string_names.h"
#include "core/input/input.h"
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
@@ -212,19 +213,27 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_
void VisualShaderGraphPlugin::update_curve(int p_node_id) {
if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) {
- if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
- links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve());
+ Ref<VisualShaderNodeCurveTexture> tex = Object::cast_to<VisualShaderNodeCurveTexture>(links[p_node_id].visual_node);
+ ERR_FAIL_COND(!tex.is_valid());
+
+ if (tex->get_texture().is_valid()) {
+ links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve());
}
+ tex->emit_signal(CoreStringNames::get_singleton()->changed);
}
}
void VisualShaderGraphPlugin::update_curve_xyz(int p_node_id) {
if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) {
- if (((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) {
- links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_x());
- links[p_node_id].curve_editors[1]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_y());
- links[p_node_id].curve_editors[2]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_z());
+ Ref<VisualShaderNodeCurveXYZTexture> tex = Object::cast_to<VisualShaderNodeCurveXYZTexture>(links[p_node_id].visual_node);
+ ERR_FAIL_COND(!tex.is_valid());
+
+ if (tex->get_texture().is_valid()) {
+ links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve_x());
+ links[p_node_id].curve_editors[1]->set_curve(tex->get_texture()->get_curve_y());
+ links[p_node_id].curve_editors[2]->set_curve(tex->get_texture()->get_curve_z());
}
+ tex->emit_signal(CoreStringNames::get_singleton()->changed);
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 9f24c5af72..5788959a77 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -335,8 +335,6 @@ class VisualShaderEditor : public VBoxContainer {
void _delete_node_request(int p_type, int p_node);
void _delete_nodes_request();
- void _removed_from_graph();
-
void _node_changed(int p_id);
void _edit_port_default_input(Object *p_button, int p_node, int p_port);
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index eb6c300d5b..f90db02c46 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -100,8 +100,6 @@ class ProjectSettingsEditor : public AcceptDialog {
void _action_reordered(const String &p_action_name, const String &p_relative_to, bool p_before);
void _update_action_map_editor();
- ProjectSettingsEditor();
-
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index fc3abbb87e..f0ec78bde6 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -55,16 +55,23 @@ void EditorQuickOpen::_build_search_cache(EditorFileSystemDirectory *p_efsd) {
_build_search_cache(p_efsd->get_subdir(i));
}
+ Vector<String> base_types = String(base_type).split(String(","));
for (int i = 0; i < p_efsd->get_file_count(); i++) {
String file_type = p_efsd->get_file_type(i);
- if (ClassDB::is_parent_class(file_type, base_type)) {
- String file = p_efsd->get_file_path(i);
- files.push_back(file.substr(6, file.length()));
-
- // Store refs to used icons.
- String ext = file.get_extension();
- if (!icons.has(ext)) {
- icons.insert(ext, get_theme_icon((has_theme_icon(file_type, SNAME("EditorIcons")) ? file_type : String("Object")), SNAME("EditorIcons")));
+ // Iterate all possible base types.
+ for (String &parent_type : base_types) {
+ if (ClassDB::is_parent_class(file_type, parent_type)) {
+ String file = p_efsd->get_file_path(i);
+ files.push_back(file.substr(6, file.length()));
+
+ // Store refs to used icons.
+ String ext = file.get_extension();
+ if (!icons.has(ext)) {
+ icons.insert(ext, get_theme_icon((has_theme_icon(file_type, SNAME("EditorIcons")) ? file_type : String("Object")), SNAME("EditorIcons")));
+ }
+
+ // Stop testing base types as soon as we got a match.
+ break;
}
}
}
diff --git a/editor/reparent_dialog.h b/editor/reparent_dialog.h
index 5c3a65a522..3fcdda7bed 100644
--- a/editor/reparent_dialog.h
+++ b/editor/reparent_dialog.h
@@ -46,7 +46,6 @@ class ReparentDialog : public ConfirmationDialog {
SceneTreeEditor *tree;
CheckBox *keep_transform;
- void update_tree();
void _reparent();
void _cancel();
@@ -56,7 +55,6 @@ protected:
public:
void set_current(const Set<Node *> &p_selection);
- String get_selected_type();
ReparentDialog();
~ReparentDialog();
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 255e026887..66000602fa 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -246,8 +246,6 @@ class SceneTreeDock : public VBoxContainer {
void _perform_instantiate_scenes(const Vector<String> &p_files, Node *parent, int p_pos);
void _replace_with_branch_scene(const String &p_file, Node *base);
- void _file_selected(String p_file);
-
void _remote_tree_selected();
void _local_tree_selected();
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 4acd5d8486..b4c40ab17a 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -114,8 +114,6 @@ class SceneTreeEditor : public Control {
void _node_visibility_changed(Node *p_node);
void _update_visibility_color(Node *p_node, TreeItem *p_item);
- void _node_replace_owner(Node *p_base, Node *p_node, Node *p_root);
-
void _selection_changed();
Node *get_scene_node();
@@ -173,7 +171,6 @@ class SceneTreeDialog : public ConfirmationDialog {
//Button *cancel;
LineEdit *filter;
- void update_tree();
void _select();
void _cancel();
void _filter_changed(const String &p_filter);
diff --git a/editor/translations/Makefile b/editor/translations/Makefile
index 1843114f06..82b3d49c59 100644
--- a/editor/translations/Makefile
+++ b/editor/translations/Makefile
@@ -18,3 +18,24 @@ merge:
check:
@for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done
+
+# Generate completion ratio from statistics string such as:
+# 2775 translated messages, 272 fuzzy translations, 151 untranslated messages.
+# First number can be 0, second and third numbers are only present if non-zero.
+include-list:
+ @list=""; \
+ threshold=0.30; \
+ for po in $(POFILES); do \
+ res=`msgfmt --statistics $$po -o /dev/null 2>&1 | sed 's/[^0-9,]*//g'`; \
+ complete=`cut -d',' -f1 <<< $$res`; \
+ fuzzy_or_untranslated=`cut -d',' -f2 <<< $$res`; \
+ untranslated_maybe=`cut -d',' -f3 <<< $$res`; \
+ if [ -z "$$fuzzy_or_untranslated" ]; then fuzzy_or_untranslated=0; fi; \
+ if [ -z "$$untranslated_maybe" ]; then untranslated_maybe=0; fi; \
+ incomplete=`expr $$fuzzy_or_untranslated + $$untranslated_maybe`; \
+ if `awk "BEGIN {exit !($$complete / ($$complete + $$incomplete) > $$threshold)}"`; then \
+ lang=`basename $$po .po`; \
+ list+="$$lang,"; \
+ fi; \
+ done; \
+ echo $$list;
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/main/main.cpp b/main/main.cpp
index a07533180a..d4a6216e35 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -376,7 +376,9 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n");
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
+ OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
#ifdef DEBUG_METHODS_ENABLED
+ // TODO: Should be removed together with nativescript eventually.
OS::get_singleton()->print(" --gdnative-generate-json-api <path> Generate JSON dump of the Godot API for GDNative bindings and save it on the file specified in <path>.\n");
OS::get_singleton()->print(" --gdnative-generate-json-builtin-api <path> Generate JSON dump of the Godot API of the builtin Variant types and utility functions for GDNative bindings and save it on the file specified in <path>.\n");
#endif
@@ -901,20 +903,24 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
auto_build_solutions = true;
editor = true;
cmdline_tool = true;
-
+#ifdef DEBUG_METHODS_ENABLED
} else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") {
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
cmdline_tool = true;
-
- // We still pass it to the main arguments since the argument handling itself is not done in this function
+ // We still pass it to the main arguments since the argument handling itself is not done in this function,
+ // it's done in nativescript init code.
main_args.push_back(I->get());
+#endif
} else if (I->get() == "--dump-extension-api") {
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
cmdline_tool = true;
dump_extension_api = true;
- print_line("dump extension?");
+ print_line("Dumping Extension API");
+ // Hack. Not needed but otherwise we end up detecting that this should
+ // run the project instead of a cmdline tool.
+ // Needs full refactoring to fix properly.
main_args.push_back(I->get());
} else if (I->get() == "--export" || I->get() == "--export-debug" ||
I->get() == "--export-pack") { // Export project
@@ -1341,8 +1347,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
display_driver_idx = 0;
}
- if (audio_driver == "") { // specified in project.godot
- audio_driver = GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
+ GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name());
+ if (audio_driver == "") { // Specified in project.godot.
+ audio_driver = GLOBAL_GET("audio/driver/driver");
}
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
@@ -2065,6 +2072,8 @@ bool Main::start() {
if (check_only) {
if (!script_res->is_valid()) {
OS::get_singleton()->set_exit_code(EXIT_FAILURE);
+ } else {
+ OS::get_singleton()->set_exit_code(EXIT_SUCCESS);
}
return false;
}
@@ -2137,7 +2146,7 @@ bool Main::start() {
}
#endif
- bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", false);
+ bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", true);
if (OS::get_singleton()->is_single_window() || (!project_manager && !editor && embed_subwindows)) {
sml->get_root()->set_embed_subwindows_hint(true);
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/dist/osx/editor.entitlements b/misc/dist/osx/editor.entitlements
index 5496f65dcc..d0137910a3 100644
--- a/misc/dist/osx/editor.entitlements
+++ b/misc/dist/osx/editor.entitlements
@@ -2,11 +2,19 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>com.apple.security.device.audio-input</key>
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
- <key>com.apple.security.device.camera</key>
+ <key>com.apple.security.cs.allow-jit</key>
+ <true/>
+ <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+ <true/>
+ <key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
+ <key>com.apple.security.device.audio-input</key>
+ <true/>
+ <key>com.apple.security.device.camera</key>
+ <true/>
</dict>
</plist>
diff --git a/misc/dist/osx/editor_mono.entitlements b/misc/dist/osx/editor_mono.entitlements
deleted file mode 100644
index c61c287652..0000000000
--- a/misc/dist/osx/editor_mono.entitlements
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>com.apple.security.cs.allow-dyld-environment-variables</key>
- <true/>
- <key>com.apple.security.cs.allow-jit</key>
- <true/>
- <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
- <true/>
- <key>com.apple.security.cs.disable-library-validation</key>
- <true/>
- <key>com.apple.security.device.audio-input</key>
- <true/>
- <key>com.apple.security.device.camera</key>
- <true/>
-</dict>
-</plist>
diff --git a/misc/hooks/pre-commit-clang-format b/misc/hooks/pre-commit-clang-format
index 81bc412944..de5d9c3f06 100755
--- a/misc/hooks/pre-commit-clang-format
+++ b/misc/hooks/pre-commit-clang-format
@@ -76,11 +76,11 @@ 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_MAX="12"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MIN="12"
+RECOMMENDED_CLANG_FORMAT_MAJOR_MAX="13"
if [ ! -x "$CLANG_FORMAT" ] ; then
- message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR.x.x."
+ message="Error: clang-format executable not found. Please install clang-format $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX."
if [ ! -t 1 ] ; then
if [ -x "$ZENITY" ] ; then
@@ -108,7 +108,7 @@ CLANG_FORMAT_VERSION="$(clang-format --version | sed "s/[^0-9\.]*\([0-9\.]*\).*/
CLANG_FORMAT_MAJOR="$(echo "$CLANG_FORMAT_VERSION" | cut -d. -f1)"
if [[ "$CLANG_FORMAT_MAJOR" -lt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MIN" || "$CLANG_FORMAT_MAJOR" -gt "$RECOMMENDED_CLANG_FORMAT_MAJOR_MAX" ]]; then
- echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN.x.x and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX.x.x)."
+ echo "Warning: Your clang-format binary is the wrong version ($CLANG_FORMAT_VERSION, expected between $RECOMMENDED_CLANG_FORMAT_MAJOR_MIN and $RECOMMENDED_CLANG_FORMAT_MAJOR_MAX)."
echo " Consider upgrading or downgrading clang-format as formatting may not be applied correctly."
fi
@@ -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/misc/scripts/compare_extension_api.py b/misc/scripts/compare_extension_api.py
new file mode 100755
index 0000000000..f96db4278c
--- /dev/null
+++ b/misc/scripts/compare_extension_api.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+
+# TODO:
+# Add a process that compares the original godot-cpp/godot-headers/extension_api.json with the new extension_api.json (both passed as arguments) and reports any API calls that have been removed.
+# If we only have additions or no changes to the file, we pass
+# For now we deem this too early because the API isn't stable enough yet.
+
+sys.exit(0)
diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h
index 7cf666c119..c8b516c951 100644
--- a/modules/bullet/area_bullet.h
+++ b/modules/bullet/area_bullet.h
@@ -145,7 +145,6 @@ public:
virtual void dispatch_callbacks();
void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status);
- void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
void scratch();
void clear_overlaps(bool p_notify);
diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp
index 81b832fb42..3a2370ff31 100644
--- a/modules/bullet/soft_body_bullet.cpp
+++ b/modules/bullet/soft_body_bullet.cpp
@@ -116,6 +116,7 @@ void SoftBodyBullet::set_soft_mesh(RID p_mesh) {
}
Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
+ ERR_FAIL_COND(arrays.is_empty());
bool success = set_trimesh_body_shape(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]);
if (!success) {
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 14e7896295..863936ab8c 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -576,6 +576,7 @@ void CSGShape3D::_validate_property(PropertyInfo &property) const {
} else if (is_collision_prefixed && !bool(get("use_collision"))) {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
+ GeometryInstance3D::_validate_property(property);
}
Array CSGShape3D::get_meshes() const {
diff --git a/modules/denoise/config.py b/modules/denoise/config.py
index 49a1f036ed..6f650354cb 100644
--- a/modules/denoise/config.py
+++ b/modules/denoise/config.py
@@ -1,11 +1,12 @@
def can_build(env, platform):
# Thirdparty dependency OpenImage Denoise includes oneDNN library
- # which only supports 64-bit architectures.
+ # and the version we use only supports x86_64.
# It's also only relevant for tools build and desktop platforms,
# as doing lightmap generation and denoising on Android or HTML5
# would be a bit far-fetched.
desktop_platforms = ["linuxbsd", "osx", "windows"]
- return env["tools"] and platform in desktop_platforms and env["bits"] == "64" and env["arch"] != "arm64"
+ supported_arch = env["bits"] == "64" and env["arch"] != "arm64" and not env["arch"].startswith("rv")
+ return env["tools"] and platform in desktop_platforms and supported_arch
def configure(env):
diff --git a/modules/fbx/tools/import_utils.cpp b/modules/fbx/tools/import_utils.cpp
index 66b0153308..bb95d120af 100644
--- a/modules/fbx/tools/import_utils.cpp
+++ b/modules/fbx/tools/import_utils.cpp
@@ -45,27 +45,27 @@ Basis ImportUtils::EulerToBasis(FBXDocParser::Model::RotOrder mode, const Vector
// by simply invert its order: https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
switch (mode) {
case FBXDocParser::Model::RotOrder_EulerXYZ:
- ret.set_euler_zyx(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_XYZ);
break;
case FBXDocParser::Model::RotOrder_EulerXZY:
- ret.set_euler_yzx(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_XZY);
break;
case FBXDocParser::Model::RotOrder_EulerYZX:
- ret.set_euler_xzy(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_YZX);
break;
case FBXDocParser::Model::RotOrder_EulerYXZ:
- ret.set_euler_zxy(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_YXZ);
break;
case FBXDocParser::Model::RotOrder_EulerZXY:
- ret.set_euler_yxz(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_ZXY);
break;
case FBXDocParser::Model::RotOrder_EulerZYX:
- ret.set_euler_xyz(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_ZYX);
break;
case FBXDocParser::Model::RotOrder_SphericXYZ:
@@ -89,22 +89,22 @@ Vector3 ImportUtils::BasisToEuler(FBXDocParser::Model::RotOrder mode, const Basi
// by simply invert its order: https://www.cs.utexas.edu/~theshark/courses/cs354/lectures/cs354-14.pdf
switch (mode) {
case FBXDocParser::Model::RotOrder_EulerXYZ:
- return p_rotation.get_euler_zyx();
+ return p_rotation.get_euler(Basis::EULER_ORDER_XYZ);
case FBXDocParser::Model::RotOrder_EulerXZY:
- return p_rotation.get_euler_yzx();
+ return p_rotation.get_euler(Basis::EULER_ORDER_XZY);
case FBXDocParser::Model::RotOrder_EulerYZX:
- return p_rotation.get_euler_xzy();
+ return p_rotation.get_euler(Basis::EULER_ORDER_YZX);
case FBXDocParser::Model::RotOrder_EulerYXZ:
- return p_rotation.get_euler_zxy();
+ return p_rotation.get_euler(Basis::EULER_ORDER_YXZ);
case FBXDocParser::Model::RotOrder_EulerZXY:
- return p_rotation.get_euler_yxz();
+ return p_rotation.get_euler(Basis::EULER_ORDER_ZXY);
case FBXDocParser::Model::RotOrder_EulerZYX:
- return p_rotation.get_euler_xyz();
+ return p_rotation.get_euler(Basis::EULER_ORDER_ZYX);
case FBXDocParser::Model::RotOrder_SphericXYZ:
// TODO
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index fb46bafb3c..368eb67fa6 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -1139,15 +1139,12 @@ void NativeScriptLanguage::profiling_start() {
MutexLock lock(mutex);
profile_data.clear();
- profiling = true;
#endif
}
void NativeScriptLanguage::profiling_stop() {
#ifdef DEBUG_ENABLED
MutexLock lock(mutex);
-
- profiling = false;
#endif
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index a7647e8c59..2364c6c0f6 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -269,7 +269,6 @@ private:
};
Map<StringName, ProfileData> profile_data;
- bool profiling = false;
public:
// These two maps must only be touched on the main thread
@@ -295,8 +294,6 @@ public:
return singleton;
}
- void _hacky_api_anchor();
-
_FORCE_INLINE_ void set_language_index(int p_idx) { lang_idx = p_idx; }
#ifndef NO_THREADS
diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h
index bdae265db2..81e711bafc 100644
--- a/modules/gdnative/pluginscript/pluginscript_instance.h
+++ b/modules/gdnative/pluginscript/pluginscript_instance.h
@@ -69,8 +69,6 @@ public:
virtual ScriptLanguage *get_language();
- void set_path(const String &p_path);
-
virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const;
virtual void refcount_incremented();
diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h
index 85a44a8cc1..f1413f0133 100644
--- a/modules/gdscript/language_server/gdscript_language_server.h
+++ b/modules/gdscript/language_server/gdscript_language_server.h
@@ -50,10 +50,8 @@ class GDScriptLanguageServer : public EditorPlugin {
private:
void _notification(int p_what);
- void _iteration();
public:
- Error parse_script_file(const String &p_path);
GDScriptLanguageServer();
void start();
void stop();
diff --git a/modules/gdscript/tests/scripts/runtime/features/stringify.gd b/modules/gdscript/tests/scripts/runtime/features/stringify.gd
index de269b92b3..fead2df854 100644
--- a/modules/gdscript/tests/scripts/runtime/features/stringify.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/stringify.gd
@@ -17,7 +17,7 @@ func test():
print(Plane(1, 2, 3, 4))
print(Quaternion(1, 2, 3, 4))
print(AABB(Vector3.ZERO, Vector3.ONE))
- print(Basis(Vector3(0, 0, 0)))
+ print(Basis.from_euler(Vector3(0, 0, 0)))
print(Transform3D.IDENTITY)
print(Color(1, 2, 3, 4))
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/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index a1d82a4649..f2f0b439a5 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -269,8 +269,6 @@ private:
Error _reparent_non_joint_skeleton_subtrees(
Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton,
const Vector<GLTFNodeIndex> &non_joints);
- Error _reparent_to_fake_joint(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton,
- const GLTFNodeIndex node_index);
Error _determine_skeleton_roots(Ref<GLTFState> state,
const GLTFSkeletonIndex skel_i);
Error _create_skeletons(Ref<GLTFState> state);
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h
index 6554c74a21..92e6ab88c4 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.h
+++ b/modules/mbedtls/packet_peer_mbed_dtls.h
@@ -59,8 +59,6 @@ protected:
Ref<SSLContextMbedTLS> ssl_ctx;
mbedtls_timing_delay_context timer;
- static void _bind_methods();
-
Error _do_handshake();
int _set_cookie();
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h
index 1b55a54a10..5692dec1b6 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/ssl_context_mbedtls.h
@@ -67,8 +67,6 @@ class SSLContextMbedTLS : public RefCounted {
protected:
bool inited = false;
- static PackedByteArray _read_file(String p_path);
-
public:
static void print_mbedtls_error(int p_ret);
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index b89d7fb238..407479e3cc 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -50,8 +50,6 @@ private:
protected:
Ref<SSLContextMbedTLS> ssl_ctx;
- static void _bind_methods();
-
Error _do_handshake();
public:
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 4c851a2989..df02d9a309 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -2,7 +2,7 @@ supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku
def can_build(env, platform):
- return True
+ return not env["arch"].startswith("rv")
def configure(env):
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/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs
index 1d7bfaf0a4..bc09e1ebf9 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs
@@ -121,15 +121,20 @@ namespace GodotTools.IdeMessaging
this.messageHandler = messageHandler;
this.logger = logger;
- // TODO: Need to fetch the project data dir name from ProjectSettings instead of defaulting to ".godot"
string projectMetadataDir = Path.Combine(godotProjectDir, ".godot", "mono", "metadata");
+ // FileSystemWatcher requires an existing directory
+ if (!Directory.Exists(projectMetadataDir)) {
+ // Check if the non hidden version exists
+ string nonHiddenProjectMetadataDir = Path.Combine(godotProjectDir, "godot", "mono", "metadata");
+ if (Directory.Exists(nonHiddenProjectMetadataDir)) {
+ projectMetadataDir = nonHiddenProjectMetadataDir;
+ } else {
+ Directory.CreateDirectory(projectMetadataDir);
+ }
+ }
MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName);
- // FileSystemWatcher requires an existing directory
- if (!Directory.Exists(projectMetadataDir))
- Directory.CreateDirectory(projectMetadataDir);
-
fsWatcher = new FileSystemWatcher(projectMetadataDir, GodotIdeMetadata.DefaultFileName);
}
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index bb6bc578a4..8fd3a13e1f 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -489,7 +489,7 @@ NavigationMeshGenerator::~NavigationMeshGenerator() {
}
void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) {
- ERR_FAIL_COND(!p_nav_mesh.is_valid());
+ ERR_FAIL_COND_MSG(!p_nav_mesh.is_valid(), "Invalid navigation mesh.");
#ifdef TOOLS_ENABLED
EditorProgress *ep(nullptr);
diff --git a/modules/raycast/config.py b/modules/raycast/config.py
index 5de36c5322..2f8bacd4ae 100644
--- a/modules/raycast/config.py
+++ b/modules/raycast/config.py
@@ -1,5 +1,7 @@
def can_build(env, platform):
# Depends on Embree library, which only supports x86_64 and aarch64.
+ if env["arch"].startswith("rv"):
+ return False
if platform == "android":
return env["android_arch"] in ["arm64v8", "x86_64"]
diff --git a/modules/regex/config.py b/modules/regex/config.py
index df9f44cb95..1248a8374d 100644
--- a/modules/regex/config.py
+++ b/modules/regex/config.py
@@ -1,5 +1,5 @@
def can_build(env, platform):
- return True
+ return not env["arch"].startswith("rv")
def configure(env):
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/modules/theora/config.py b/modules/theora/config.py
index b063ed51f9..7f354a8fda 100644
--- a/modules/theora/config.py
+++ b/modules/theora/config.py
@@ -1,4 +1,6 @@
def can_build(env, platform):
+ if env["arch"].startswith("rv"):
+ return False
return env.module_check_dependencies("theora", ["ogg", "vorbis"])
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index bf2d8e9683..78881f0a53 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -90,12 +90,6 @@ public:
void set_stack_size(int p_size);
int get_stack_size() const;
- void set_return_type_enabled(bool p_returns);
- bool is_return_type_enabled() const;
-
- void set_return_type(Variant::Type p_type);
- Variant::Type get_return_type() const;
-
void set_rpc_mode(Multiplayer::RPCMode p_mode);
Multiplayer::RPCMode get_rpc_mode() const;
diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h
index e3efaddba2..fcc2513f3f 100644
--- a/platform/android/audio_driver_opensl.h
+++ b/platform/android/audio_driver_opensl.h
@@ -59,7 +59,6 @@ class AudioDriverOpenSL : public AudioDriver {
SLObjectItf sl;
SLEngineItf EngineItf;
SLObjectItf OutputMix;
- SLVolumeItf volumeItf;
SLObjectItf player;
SLObjectItf recorder;
SLAndroidSimpleBufferQueueItf bufferQueueItf;
@@ -68,7 +67,6 @@ class AudioDriverOpenSL : public AudioDriver {
SLDataFormat_PCM pcm;
SLDataSink audioSink;
SLDataLocator_OutputMix locator_outputmix;
- SLBufferQueueState state;
static AudioDriverOpenSL *s_ad;
@@ -89,8 +87,6 @@ class AudioDriverOpenSL : public AudioDriver {
virtual Error capture_init_device();
public:
- void set_singleton();
-
virtual const char *get_name() const;
virtual Error init();
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/android/os_android.cpp b/platform/android/os_android.cpp
index 034885aa32..94ca51f75a 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -263,7 +263,6 @@ Size2i OS_Android::get_display_size() const {
void OS_Android::set_context_is_16_bits(bool p_is_16) {
#if defined(OPENGL_ENABLED)
- //use_16bits_fbo = p_is_16;
//if (rasterizer)
// rasterizer->set_force_16_bits_fbo(p_is_16);
#endif
@@ -325,7 +324,6 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god
#if defined(OPENGL_ENABLED)
gl_extensions = nullptr;
use_gl2 = false;
- use_16bits_fbo = false;
#endif
#if defined(VULKAN_ENABLED)
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index ce8083388f..9bb37325cf 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -48,7 +48,6 @@ private:
bool use_apk_expansion;
#if defined(OPENGL_ENABLED)
- bool use_16bits_fbo;
const char *gl_extensions;
#endif
diff --git a/platform/javascript/package-lock.json b/platform/javascript/package-lock.json
index 8003619576..1bc11c7ccf 100644
--- a/platform/javascript/package-lock.json
+++ b/platform/javascript/package-lock.json
@@ -109,9 +109,9 @@
"dev": true
},
"ansi-regex": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
- "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 1b9dd1e8f3..4b3804d049 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -119,6 +119,13 @@ def configure(env):
if env["bits"] == "default":
env["bits"] = "64" if is64 else "32"
+ if env["arch"] == "" and platform.machine() == "riscv64":
+ env["arch"] = "rv64"
+
+ if env["arch"] == "rv64":
+ # G = General-purpose extensions, C = Compression extension (very common).
+ env.Append(CCFLAGS=["-march=rv64gc"])
+
## Compiler configuration
if "CXX" in env and "clang" in os.path.basename(env["CXX"]):
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index f2cd336b39..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: {
}
@@ -406,6 +407,20 @@ void DisplayServerX11::clipboard_set(const String &p_text) {
XSetSelectionOwner(x11_display, XInternAtom(x11_display, "CLIPBOARD", 0), windows[MAIN_WINDOW_ID].x11_window, CurrentTime);
}
+void DisplayServerX11::clipboard_set_primary(const String &p_text) {
+ _THREAD_SAFE_METHOD_
+ if (!p_text.is_empty()) {
+ {
+ // The clipboard content can be accessed while polling for events.
+ MutexLock mutex_lock(events_mutex);
+ internal_clipboard_primary = p_text;
+ }
+
+ XSetSelectionOwner(x11_display, XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window, CurrentTime);
+ XSetSelectionOwner(x11_display, XInternAtom(x11_display, "PRIMARY", 0), windows[MAIN_WINDOW_ID].x11_window, CurrentTime);
+ }
+}
+
Bool DisplayServerX11::_predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg) {
if (event->type == SelectionNotify && event->xselection.requestor == *(Window *)arg) {
return True;
@@ -427,7 +442,12 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A
Window selection_owner = XGetSelectionOwner(x11_display, p_source);
if (selection_owner == x11_window) {
- return internal_clipboard;
+ static const char *target_type = "PRIMARY";
+ if (p_source != None && String(XGetAtomName(x11_display, p_source)) == target_type) {
+ return internal_clipboard_primary;
+ } else {
+ return internal_clipboard;
+ }
}
if (selection_owner != None) {
@@ -580,6 +600,19 @@ String DisplayServerX11::clipboard_get() const {
return ret;
}
+String DisplayServerX11::clipboard_get_primary() const {
+ _THREAD_SAFE_METHOD_
+
+ String ret;
+ ret = _clipboard_get(XInternAtom(x11_display, "PRIMARY", 0), windows[MAIN_WINDOW_ID].x11_window);
+
+ if (ret.is_empty()) {
+ ret = _clipboard_get(XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window);
+ }
+
+ return ret;
+}
+
Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) {
if (event->xany.window == *(Window *)arg) {
return (event->type == SelectionRequest) ||
@@ -2417,7 +2450,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
Input::get_singleton()->parse_input_event(k);
}
-Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const {
+Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property, Atom p_selection) const {
if (p_target == XInternAtom(x11_display, "TARGETS", 0)) {
// Request to list all supported targets.
Atom data[9];
@@ -2459,7 +2492,13 @@ Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p
p_target == XInternAtom(x11_display, "text/plain", 0)) {
// Directly using internal clipboard because we know our window
// is the owner during a selection request.
- CharString clip = internal_clipboard.utf8();
+ CharString clip;
+ static const char *target_type = "PRIMARY";
+ if (p_selection != None && String(XGetAtomName(x11_display, p_selection)) == target_type) {
+ clip = internal_clipboard_primary.utf8();
+ } else {
+ clip = internal_clipboard.utf8();
+ }
XChangeProperty(x11_display,
p_requestor,
p_property,
@@ -2497,7 +2536,7 @@ void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p
for (uint64_t i = 0; i < len; i += 2) {
Atom target = targets[i];
Atom &property = targets[i + 1];
- property = _process_selection_request_target(target, p_event->requestor, property);
+ property = _process_selection_request_target(target, p_event->requestor, property, p_event->selection);
}
XChangeProperty(x11_display,
@@ -2515,7 +2554,7 @@ void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p
}
} else {
// Request for target conversion.
- respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property);
+ respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property, p_event->selection);
}
respond.xselection.type = SelectionNotify;
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 1887c7105b..ded481f613 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -155,6 +155,7 @@ class DisplayServerX11 : public DisplayServer {
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect);
String internal_clipboard;
+ String internal_clipboard_primary;
Window xdnd_source_window;
::Display *x11_display;
char *xmbstring;
@@ -205,7 +206,7 @@ class DisplayServerX11 : public DisplayServer {
void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo = false);
- Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const;
+ Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property, Atom p_selection) const;
void _handle_selection_request_event(XSelectionRequestEvent *p_event) const;
String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const;
@@ -290,6 +291,8 @@ public:
virtual void clipboard_set(const String &p_text) override;
virtual String clipboard_get() const override;
+ virtual void clipboard_set_primary(const String &p_text) override;
+ virtual String clipboard_get_primary() const override;
virtual int get_screen_count() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index c060c3d523..3048ecf39e 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -106,7 +106,6 @@ private:
int get_joy_ref(IOHIDDeviceRef p_device) const;
void poll_joypads() const;
- void setup_joypad_objects();
void config_hid_manager(CFArrayRef p_matching_array) const;
void joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp);
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 7945f409a1..9398573ee1 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -117,11 +117,6 @@ private:
Windows::System::Display::DisplayRequest ^ display_request;
- void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed);
-
- void _drag_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void _touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam);
-
ref class ManagedType {
public:
property bool alert_close_handle;
diff --git a/scene/2d/audio_listener_2d.h b/scene/2d/audio_listener_2d.h
index 875887acc6..454053bc4a 100644
--- a/scene/2d/audio_listener_2d.h
+++ b/scene/2d/audio_listener_2d.h
@@ -43,8 +43,6 @@ private:
friend class Viewport;
protected:
- void _update_listener();
-
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index 6916f832d0..28facd09ce 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -454,7 +454,7 @@ void CollisionObject2D::shape_owner_clear_shapes(uint32_t p_owner) {
}
uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const {
- ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);
+ ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, UINT32_MAX);
for (const KeyValue<uint32_t, ShapeData> &E : shapes) {
for (int i = 0; i < E.value.shapes.size(); i++) {
@@ -465,7 +465,7 @@ uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const {
}
//in theory it should be unreachable
- return 0;
+ ERR_FAIL_V_MSG(UINT32_MAX, "Can't find owner for shape index " + itos(p_shape_index) + ".");
}
void CollisionObject2D::set_pickable(bool p_enabled) {
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/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h
index 4990d443e3..391f51224e 100644
--- a/scene/2d/cpu_particles_2d.h
+++ b/scene/2d/cpu_particles_2d.h
@@ -201,7 +201,6 @@ public:
void set_explosiveness_ratio(real_t p_ratio);
void set_randomness_ratio(real_t p_ratio);
void set_lifetime_randomness(double p_random);
- void set_visibility_aabb(const Rect2 &p_aabb);
void set_use_local_coordinates(bool p_enable);
void set_speed_scale(double p_scale);
@@ -213,7 +212,6 @@ public:
real_t get_explosiveness_ratio() const;
real_t get_randomness_ratio() const;
double get_lifetime_randomness() const;
- Rect2 get_visibility_aabb() const;
bool get_use_local_coordinates() const;
double get_speed_scale() const;
@@ -226,9 +224,6 @@ public:
void set_draw_order(DrawOrder p_order);
DrawOrder get_draw_order() const;
- void set_draw_passes(int p_count);
- int get_draw_passes() const;
-
void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const;
@@ -264,7 +259,6 @@ public:
void set_emission_points(const Vector<Vector2> &p_points);
void set_emission_normals(const Vector<Vector2> &p_normals);
void set_emission_colors(const Vector<Color> &p_colors);
- void set_emission_point_count(int p_count);
void set_scale_curve_x(Ref<Curve> p_scale_curve);
void set_scale_curve_y(Ref<Curve> p_scale_curve);
void set_split_scale(bool p_split_scale);
@@ -275,7 +269,6 @@ public:
Vector<Vector2> get_emission_points() const;
Vector<Vector2> get_emission_normals() const;
Vector<Color> get_emission_colors() const;
- int get_emission_point_count() const;
Ref<Curve> get_scale_curve_x() const;
Ref<Curve> get_scale_curve_y() const;
bool get_split_scale();
diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp
index 3637594e1b..6950fefdbe 100644
--- a/scene/2d/gpu_particles_2d.cpp
+++ b/scene/2d/gpu_particles_2d.cpp
@@ -532,6 +532,7 @@ void GPUParticles2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_trail_section_subdivisions"), &GPUParticles2D::get_trail_section_subdivisions);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
+ ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false.
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_GROUP("Time", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime");
diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp
index 15008390b7..58bff97da9 100644
--- a/scene/2d/mesh_instance_2d.cpp
+++ b/scene/2d/mesh_instance_2d.cpp
@@ -96,6 +96,10 @@ Rect2 MeshInstance2D::_edit_get_rect() const {
return Node2D::_edit_get_rect();
}
+
+bool MeshInstance2D::_edit_use_rect() const {
+ return mesh.is_valid();
+}
#endif
MeshInstance2D::MeshInstance2D() {
diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h
index adfda4cf7f..f94d53da7d 100644
--- a/scene/2d/mesh_instance_2d.h
+++ b/scene/2d/mesh_instance_2d.h
@@ -48,6 +48,7 @@ protected:
public:
#ifdef TOOLS_ENABLED
virtual Rect2 _edit_get_rect() const override;
+ virtual bool _edit_use_rect() const override;
#endif
void set_mesh(const Ref<Mesh> &p_mesh);
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 2f00978123..7faa964407 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -184,7 +184,7 @@ Vector2 NavigationAgent2D::get_target_location() const {
Vector2 NavigationAgent2D::get_next_location() {
update_navigation();
if (navigation_path.size() == 0) {
- ERR_FAIL_COND_V(agent_parent == nullptr, Vector2());
+ ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent.");
return agent_parent->get_global_position();
} else {
return navigation_path[nav_path_index];
@@ -192,7 +192,7 @@ Vector2 NavigationAgent2D::get_next_location() {
}
real_t NavigationAgent2D::distance_to_target() const {
- ERR_FAIL_COND_V(agent_parent == nullptr, 0.0);
+ ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
return agent_parent->get_global_position().distance_to(target_location);
}
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/area_3d.cpp b/scene/3d/area_3d.cpp
index d411525707..9179983220 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -580,6 +580,8 @@ void Area3D::_validate_property(PropertyInfo &property) const {
property.hint_string = options;
}
+
+ CollisionObject3D::_validate_property(property);
}
void Area3D::_bind_methods() {
diff --git a/scene/3d/audio_listener_3d.h b/scene/3d/audio_listener_3d.h
index 492cacb0e9..31de3b4fb1 100644
--- a/scene/3d/audio_listener_3d.h
+++ b/scene/3d/audio_listener_3d.h
@@ -63,9 +63,6 @@ public:
virtual Transform3D get_listener_transform() const;
- void set_visible_layers(uint32_t p_layers);
- uint32_t get_visible_layers() const;
-
AudioListener3D();
~AudioListener3D();
};
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 44a685f506..261acbeeb9 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -638,6 +638,8 @@ void AudioStreamPlayer3D::_validate_property(PropertyInfo &property) const {
property.hint_string = options;
}
+
+ Node3D::_validate_property(property);
}
void AudioStreamPlayer3D::_bus_layout_changed() {
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index 8e89f4fc54..5dc7382197 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -58,6 +58,8 @@ void BoneAttachment3D::_validate_property(PropertyInfo &property) const {
property.hint_string = "";
}
}
+
+ Node3D::_validate_property(property);
}
bool BoneAttachment3D::_set(const StringName &p_path, const Variant &p_value) {
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 588d2b5018..af3b3ae5bc 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -71,6 +71,8 @@ void Camera3D::_validate_property(PropertyInfo &p_property) const {
p_property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
+
+ Node3D::_validate_property(p_property);
}
void Camera3D::_update_camera() {
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 814ed5c2a7..fd891a5e13 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -648,7 +648,7 @@ void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) {
}
uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
- ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0);
+ ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, UINT32_MAX);
for (const KeyValue<uint32_t, ShapeData> &E : shapes) {
for (int i = 0; i < E.value.shapes.size(); i++) {
@@ -659,7 +659,7 @@ uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const {
}
//in theory it should be unreachable
- return 0;
+ ERR_FAIL_V_MSG(UINT32_MAX, "Can't find owner for shape index " + itos(p_shape_index) + ".");
}
CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 48ef41e015..f1e800988d 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);
@@ -531,6 +532,8 @@ void CPUParticles3D::_validate_property(PropertyInfo &property) const {
if (property.name.begins_with("scale_curve_") && !split_scale) {
property.usage = PROPERTY_USAGE_NONE;
}
+
+ Node3D::_validate_property(property);
}
static uint32_t idhash(uint32_t x) {
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index 160814ead4..aca7328a27 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -209,7 +209,6 @@ public:
void set_explosiveness_ratio(real_t p_ratio);
void set_randomness_ratio(real_t p_ratio);
void set_lifetime_randomness(double p_random);
- void set_visibility_aabb(const AABB &p_aabb);
void set_use_local_coordinates(bool p_enable);
void set_speed_scale(double p_scale);
@@ -221,7 +220,6 @@ public:
real_t get_explosiveness_ratio() const;
real_t get_randomness_ratio() const;
double get_lifetime_randomness() const;
- AABB get_visibility_aabb() const;
bool get_use_local_coordinates() const;
double get_speed_scale() const;
@@ -234,9 +232,6 @@ public:
void set_draw_order(DrawOrder p_order);
DrawOrder get_draw_order() const;
- void set_draw_passes(int p_count);
- int get_draw_passes() const;
-
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh() const;
@@ -275,7 +270,6 @@ public:
void set_emission_points(const Vector<Vector3> &p_points);
void set_emission_normals(const Vector<Vector3> &p_normals);
void set_emission_colors(const Vector<Color> &p_colors);
- void set_emission_point_count(int p_count);
void set_emission_ring_axis(Vector3 p_axis);
void set_emission_ring_height(real_t p_height);
void set_emission_ring_radius(real_t p_radius);
@@ -291,7 +285,6 @@ public:
Vector<Vector3> get_emission_points() const;
Vector<Vector3> get_emission_normals() const;
Vector<Color> get_emission_colors() const;
- int get_emission_point_count() const;
Vector3 get_emission_ring_axis() const;
real_t get_emission_ring_height() const;
real_t get_emission_ring_radius() const;
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index c94a99a203..e3c63d62f9 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -160,6 +160,7 @@ void Decal::_validate_property(PropertyInfo &property) const {
if (!distance_fade_enabled && (property.name == "distance_fade_begin" || property.name == "distance_fade_length")) {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
+ VisualInstance3D::_validate_property(property);
}
TypedArray<String> Decal::get_configuration_warnings() const {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 32a62d8c7e..13cb8b7dfb 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -388,6 +388,8 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const {
return;
}
}
+
+ GeometryInstance3D::_validate_property(property);
}
void GPUParticles3D::emit_particle(const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
@@ -562,6 +564,7 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting");
+ ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false.
ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter");
ADD_GROUP("Time", "");
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index c787ba5087..fbdbd79c0c 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -200,21 +200,11 @@ void Light3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
- if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_size") {
- property.usage = PROPERTY_USAGE_NONE;
- }
-
- if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_specular") {
- property.usage = PROPERTY_USAGE_NONE;
- }
-
- if (get_light_type() == RS::LIGHT_DIRECTIONAL && property.name == "light_projector") {
- property.usage = PROPERTY_USAGE_NONE;
- }
-
if (get_light_type() != RS::LIGHT_DIRECTIONAL && property.name == "light_angular_distance") {
+ // Angular distance is only used in DirectionalLight3D.
property.usage = PROPERTY_USAGE_NONE;
}
+ VisualInstance3D::_validate_property(property);
}
void Light3D::_bind_methods() {
@@ -361,6 +351,7 @@ Light3D::~Light3D() {
void DirectionalLight3D::set_shadow_mode(ShadowMode p_mode) {
shadow_mode = p_mode;
RS::get_singleton()->light_directional_set_shadow_mode(light, RS::LightDirectionalShadowMode(p_mode));
+ notify_property_list_changed();
}
DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const {
@@ -385,6 +376,25 @@ bool DirectionalLight3D::is_sky_only() const {
return sky_only;
}
+void DirectionalLight3D::_validate_property(PropertyInfo &property) const {
+ if (shadow_mode == SHADOW_ORTHOGONAL && (property.name == "directional_shadow_split_1" || property.name == "directional_shadow_blend_splits")) {
+ // Split 2 and split blending are only used with the PSSM 2 Splits and PSSM 4 Splits shadow modes.
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
+ if ((shadow_mode == SHADOW_ORTHOGONAL || shadow_mode == SHADOW_PARALLEL_2_SPLITS) && (property.name == "directional_shadow_split_2" || property.name == "directional_shadow_split_3")) {
+ // Splits 3 and 4 are only used with the PSSM 4 Splits shadow mode.
+ property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+
+ if (property.name == "light_size" || property.name == "light_projector" || property.name == "light_specular") {
+ // Not implemented in DirectionalLight3D (`light_size` is replaced by `light_angular_distance`).
+ property.usage = PROPERTY_USAGE_NONE;
+ }
+
+ Light3D::_validate_property(property);
+}
+
void DirectionalLight3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode);
ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode);
@@ -400,8 +410,8 @@ void DirectionalLight3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_2", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_3", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_3_OFFSET);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional_shadow_blend_splits"), "set_blend_splits", "is_blend_splits_enabled");
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_fade_start", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SHADOW_FADE_START);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_RANGE, "0,8192,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_RANGE, "0,1024,0.1,or_greater,exp"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE);
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index f788c323f7..a9f5ce27b4 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -152,6 +152,7 @@ private:
protected:
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const override;
public:
void set_shadow_mode(ShadowMode p_mode);
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index b56f0fd145..3bcb6add76 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1370,6 +1370,7 @@ void LightmapGI::_validate_property(PropertyInfo &property) const {
if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
property.usage = PROPERTY_USAGE_NONE;
}
+ VisualInstance3D::_validate_property(property);
}
void LightmapGI::_bind_methods() {
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index c2d5c757db..1bc7d20c19 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -192,7 +192,7 @@ Vector3 NavigationAgent3D::get_target_location() const {
Vector3 NavigationAgent3D::get_next_location() {
update_navigation();
if (navigation_path.size() == 0) {
- ERR_FAIL_COND_V(agent_parent == nullptr, Vector3());
+ ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector3(), "The agent has no parent.");
return agent_parent->get_global_transform().origin;
} else {
return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0);
@@ -200,7 +200,7 @@ Vector3 NavigationAgent3D::get_next_location() {
}
real_t NavigationAgent3D::distance_to_target() const {
- ERR_FAIL_COND_V(agent_parent == nullptr, 0.0);
+ ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
return agent_parent->get_global_transform().origin.distance_to(target_location);
}
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 8a51a259f7..473368cf69 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -162,7 +162,7 @@ void _bake_navigation_mesh(void *p_user_data) {
}
void NavigationRegion3D::bake_navigation_mesh() {
- ERR_FAIL_COND(bake_thread.is_started());
+ ERR_FAIL_COND_MSG(bake_thread.is_started(), "Unable to start another bake request. The navigation mesh bake thread is already baking a navigation mesh.");
BakeThreadsArgs *args = memnew(BakeThreadsArgs);
args->nav_region = this;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index c96204cf60..8a39d4d30f 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -220,6 +220,13 @@ void Node3D::_notification(int p_what) {
}
}
+void Node3D::set_basis(const Basis &p_basis) {
+ set_transform(Transform3D(p_basis, data.local_transform.origin));
+}
+void Node3D::set_quaternion(const Quaternion &p_quaternion) {
+ set_transform(Transform3D(Basis(p_quaternion), data.local_transform.origin));
+}
+
void Node3D::set_transform(const Transform3D &p_transform) {
data.local_transform = p_transform;
data.dirty |= DIRTY_VECTORS;
@@ -229,6 +236,13 @@ void Node3D::set_transform(const Transform3D &p_transform) {
}
}
+Basis Node3D::get_basis() const {
+ return get_transform().basis;
+}
+Quaternion Node3D::get_quaternion() const {
+ return Quaternion(get_transform().basis);
+}
+
void Node3D::set_global_transform(const Transform3D &p_transform) {
Transform3D xform =
(data.parent && !data.top_level_active) ?
@@ -308,6 +322,45 @@ void Node3D::set_position(const Vector3 &p_position) {
}
}
+void Node3D::set_rotation_edit_mode(RotationEditMode p_mode) {
+ if (data.rotation_edit_mode == p_mode) {
+ return;
+ }
+ data.rotation_edit_mode = p_mode;
+ notify_property_list_changed();
+}
+
+Node3D::RotationEditMode Node3D::get_rotation_edit_mode() const {
+ return data.rotation_edit_mode;
+}
+
+void Node3D::set_rotation_order(RotationOrder p_order) {
+ Basis::EulerOrder order = Basis::EulerOrder(p_order);
+
+ if (data.rotation_order == order) {
+ return;
+ }
+
+ ERR_FAIL_INDEX(int32_t(order), 6);
+
+ if (data.dirty & DIRTY_VECTORS) {
+ data.rotation = data.local_transform.basis.get_euler_normalized(order);
+ data.scale = data.local_transform.basis.get_scale();
+ data.dirty &= ~DIRTY_VECTORS;
+ } else {
+ data.rotation = Basis::from_euler(data.rotation, data.rotation_order).get_euler_normalized(order);
+ }
+
+ data.rotation_order = order;
+ //changing rotation order should not affect transform
+
+ notify_property_list_changed(); //will change rotation
+}
+
+Node3D::RotationOrder Node3D::get_rotation_order() const {
+ return RotationOrder(data.rotation_order);
+}
+
void Node3D::set_rotation(const Vector3 &p_euler_rad) {
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
@@ -324,7 +377,7 @@ void Node3D::set_rotation(const Vector3 &p_euler_rad) {
void Node3D::set_scale(const Vector3 &p_scale) {
if (data.dirty & DIRTY_VECTORS) {
- data.rotation = data.local_transform.basis.get_rotation();
+ data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order);
data.dirty &= ~DIRTY_VECTORS;
}
@@ -343,7 +396,7 @@ Vector3 Node3D::get_position() const {
Vector3 Node3D::get_rotation() const {
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
- data.rotation = data.local_transform.basis.get_rotation();
+ data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order);
data.dirty &= ~DIRTY_VECTORS;
}
@@ -354,7 +407,7 @@ Vector3 Node3D::get_rotation() const {
Vector3 Node3D::get_scale() const {
if (data.dirty & DIRTY_VECTORS) {
data.scale = data.local_transform.basis.get_scale();
- data.rotation = data.local_transform.basis.get_rotation();
+ data.rotation = data.local_transform.basis.get_euler_normalized(data.rotation_order);
data.dirty &= ~DIRTY_VECTORS;
}
@@ -484,14 +537,14 @@ void Node3D::_update_gizmos() {
#endif
}
-#ifdef TOOLS_ENABLED
void Node3D::set_disable_gizmos(bool p_enabled) {
+#ifdef TOOLS_ENABLED
data.gizmos_disabled = p_enabled;
if (!p_enabled) {
clear_gizmos();
}
-}
#endif
+}
void Node3D::set_disable_scale(bool p_enabled) {
data.disable_scale = p_enabled;
@@ -780,6 +833,24 @@ NodePath Node3D::get_visibility_parent() const {
return visibility_parent_path;
}
+void Node3D::_validate_property(PropertyInfo &property) const {
+ if (data.rotation_edit_mode != ROTATION_EDIT_MODE_BASIS && property.name == "basis") {
+ property.usage = 0;
+ }
+ if (data.rotation_edit_mode == ROTATION_EDIT_MODE_BASIS && property.name == "scale") {
+ property.usage = 0;
+ }
+ if (data.rotation_edit_mode != ROTATION_EDIT_MODE_QUATERNION && property.name == "quaternion") {
+ property.usage = 0;
+ }
+ if (data.rotation_edit_mode != ROTATION_EDIT_MODE_EULER && property.name == "rotation") {
+ property.usage = 0;
+ }
+ if (data.rotation_edit_mode != ROTATION_EDIT_MODE_EULER && property.name == "rotation_order") {
+ property.usage = 0;
+ }
+}
+
void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "local"), &Node3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
@@ -787,8 +858,16 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &Node3D::get_position);
ClassDB::bind_method(D_METHOD("set_rotation", "euler"), &Node3D::set_rotation);
ClassDB::bind_method(D_METHOD("get_rotation"), &Node3D::get_rotation);
+ ClassDB::bind_method(D_METHOD("set_rotation_order", "order"), &Node3D::set_rotation_order);
+ ClassDB::bind_method(D_METHOD("get_rotation_order"), &Node3D::get_rotation_order);
+ ClassDB::bind_method(D_METHOD("set_rotation_edit_mode", "edit_mode"), &Node3D::set_rotation_edit_mode);
+ ClassDB::bind_method(D_METHOD("get_rotation_edit_mode"), &Node3D::get_rotation_edit_mode);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Node3D::set_scale);
ClassDB::bind_method(D_METHOD("get_scale"), &Node3D::get_scale);
+ ClassDB::bind_method(D_METHOD("set_quaternion", "quaternion"), &Node3D::set_quaternion);
+ ClassDB::bind_method(D_METHOD("get_quaternion"), &Node3D::get_quaternion);
+ ClassDB::bind_method(D_METHOD("set_basis", "basis"), &Node3D::set_basis);
+ ClassDB::bind_method(D_METHOD("get_basis"), &Node3D::get_basis);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Node3D::set_global_transform);
ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform);
ClassDB::bind_method(D_METHOD("get_parent_node_3d"), &Node3D::get_parent_node_3d);
@@ -848,15 +927,29 @@ void Node3D::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_EXIT_WORLD);
BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
+ BIND_ENUM_CONSTANT(ROTATION_EDIT_MODE_EULER);
+ BIND_ENUM_CONSTANT(ROTATION_EDIT_MODE_QUATERNION);
+ BIND_ENUM_CONSTANT(ROTATION_EDIT_MODE_BASIS);
+
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_XYZ);
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_XZY);
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_YXZ);
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_YZX);
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_ZXY);
+ BIND_ENUM_CONSTANT(ROTATION_ORDER_ZYX);
+
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM3D,"transform/global",PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR ), "set_global_transform", "get_global_transform") ;
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion");
+ ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_edit_mode", PROPERTY_HINT_ENUM, "Euler,Quaternion,Basis"), "set_rotation_edit_mode", "get_rotation_edit_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_order", PROPERTY_HINT_ENUM, "XYZ,XZY,YXZ,YZX,ZXY,ZYX"), "set_rotation_order", "get_rotation_order");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
- ADD_GROUP("Matrix", "");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_transform", "get_transform");
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index d6dcdd96fe..3e21eb12be 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -51,6 +51,23 @@ class Node3D : public Node {
GDCLASS(Node3D, Node);
OBJ_CATEGORY("3D");
+public:
+ enum RotationEditMode {
+ ROTATION_EDIT_MODE_EULER,
+ ROTATION_EDIT_MODE_QUATERNION,
+ ROTATION_EDIT_MODE_BASIS,
+ };
+
+ enum RotationOrder {
+ ROTATION_ORDER_XYZ,
+ ROTATION_ORDER_XZY,
+ ROTATION_ORDER_YXZ,
+ ROTATION_ORDER_YZX,
+ ROTATION_ORDER_ZXY,
+ ROTATION_ORDER_ZYX
+ };
+
+private:
enum TransformDirty {
DIRTY_NONE = 0,
DIRTY_VECTORS = 1,
@@ -63,8 +80,10 @@ class Node3D : public Node {
struct Data {
mutable Transform3D global_transform;
mutable Transform3D local_transform;
+ mutable Basis::EulerOrder rotation_order = Basis::EULER_ORDER_YXZ;
mutable Vector3 rotation;
mutable Vector3 scale = Vector3(1, 1, 1);
+ mutable RotationEditMode rotation_edit_mode = ROTATION_EDIT_MODE_EULER;
mutable int dirty = DIRTY_NONE;
@@ -116,6 +135,8 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const override;
+
public:
enum {
NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED,
@@ -130,17 +151,28 @@ public:
Ref<World3D> get_world_3d() const;
void set_position(const Vector3 &p_position);
+
+ void set_rotation_edit_mode(RotationEditMode p_mode);
+ RotationEditMode get_rotation_edit_mode() const;
+
+ void set_rotation_order(RotationOrder p_order);
void set_rotation(const Vector3 &p_euler_rad);
void set_scale(const Vector3 &p_scale);
Vector3 get_position() const;
+
+ RotationOrder get_rotation_order() const;
Vector3 get_rotation() const;
Vector3 get_scale() const;
void set_transform(const Transform3D &p_transform);
+ void set_basis(const Basis &p_basis);
+ void set_quaternion(const Quaternion &p_quaternion);
void set_global_transform(const Transform3D &p_transform);
Transform3D get_transform() const;
+ Basis get_basis() const;
+ Quaternion get_quaternion() const;
Transform3D get_global_transform() const;
#ifdef TOOLS_ENABLED
@@ -214,4 +246,7 @@ public:
Node3D();
};
+VARIANT_ENUM_CAST(Node3D::RotationEditMode)
+VARIANT_ENUM_CAST(Node3D::RotationOrder)
+
#endif // NODE_3D_H
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 9ea37e4bfa..a0eac76e39 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -248,6 +248,7 @@ void PathFollow3D::_validate_property(PropertyInfo &property) const {
property.hint_string = "0," + rtos(max) + ",0.01,or_lesser,or_greater";
}
+ Node3D::_validate_property(property);
}
TypedArray<String> PathFollow3D::get_configuration_warnings() const {
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 8cb348d6e3..4f1003839e 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1059,6 +1059,7 @@ void RigidDynamicBody3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
+ PhysicsBody3D::_validate_property(property);
}
RigidDynamicBody3D::RigidDynamicBody3D() :
@@ -1933,6 +1934,7 @@ void CharacterBody3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
+ PhysicsBody3D::_validate_property(property);
}
CharacterBody3D::CharacterBody3D() :
@@ -3060,7 +3062,7 @@ void PhysicalBone3D::set_joint_rotation(const Vector3 &p_euler_rad) {
}
Vector3 PhysicalBone3D::get_joint_rotation() const {
- return joint_offset.basis.get_rotation();
+ return joint_offset.basis.get_euler_normalized();
}
const Transform3D &PhysicalBone3D::get_body_offset() const {
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index 719dbedd94..29c382cd05 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -188,6 +188,7 @@ void ReflectionProbe::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
}
}
+ VisualInstance3D::_validate_property(property);
}
void ReflectionProbe::_bind_methods() {
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index d5fb1fa6ab..d890609e23 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -68,7 +68,7 @@ void RemoteTransform3D::_update_remote() {
Transform3D our_trans = get_global_transform();
if (update_remote_rotation) {
- n->set_rotation(our_trans.basis.get_rotation());
+ n->set_rotation(our_trans.basis.get_euler_normalized(Basis::EulerOrder(n->get_rotation_order())));
}
if (update_remote_scale) {
@@ -90,7 +90,7 @@ void RemoteTransform3D::_update_remote() {
Transform3D our_trans = get_transform();
if (update_remote_rotation) {
- n->set_rotation(our_trans.basis.get_rotation());
+ n->set_rotation(our_trans.basis.get_euler_normalized(Basis::EulerOrder(n->get_rotation_order())));
}
if (update_remote_scale) {
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/3d/skeleton_ik_3d.cpp b/scene/3d/skeleton_ik_3d.cpp
index 2e788051f4..1498955ec0 100644
--- a/scene/3d/skeleton_ik_3d.cpp
+++ b/scene/3d/skeleton_ik_3d.cpp
@@ -351,6 +351,8 @@ void SkeletonIK3D::_validate_property(PropertyInfo &property) const {
property.hint_string = "";
}
}
+
+ Node::_validate_property(property);
}
void SkeletonIK3D::_bind_methods() {
diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h
index 4cf08e7c99..ccb25bcd4c 100644
--- a/scene/3d/skeleton_ik_3d.h
+++ b/scene/3d/skeleton_ik_3d.h
@@ -137,8 +137,7 @@ class SkeletonIK3D : public Node {
FabrikInverseKinematic::Task *task = nullptr;
protected:
- virtual void
- _validate_property(PropertyInfo &property) const override;
+ virtual void _validate_property(PropertyInfo &property) const override;
static void _bind_methods();
virtual void _notification(int p_what);
diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp
index 9fceb21790..903eedb58b 100644
--- a/scene/3d/soft_dynamic_body_3d.cpp
+++ b/scene/3d/soft_dynamic_body_3d.cpp
@@ -250,7 +250,7 @@ void SoftDynamicBody3D::_notification(int p_what) {
RID space = get_world_3d()->get_space();
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space);
- prepare_physics_server();
+ _prepare_physics_server();
} break;
case NOTIFICATION_READY: {
@@ -284,13 +284,13 @@ void SoftDynamicBody3D::_notification(int p_what) {
case NOTIFICATION_DISABLED: {
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
- prepare_physics_server();
+ _prepare_physics_server();
}
} break;
case NOTIFICATION_ENABLED: {
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
- prepare_physics_server();
+ _prepare_physics_server();
}
} break;
@@ -378,7 +378,7 @@ void SoftDynamicBody3D::_bind_methods() {
TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
- if (get_mesh().is_null()) {
+ if (mesh.is_null()) {
warnings.push_back(TTR("This body will be ignored until you set a mesh."));
}
@@ -407,11 +407,17 @@ void SoftDynamicBody3D::_update_physics_server() {
}
void SoftDynamicBody3D::_draw_soft_mesh() {
- if (get_mesh().is_null()) {
+ if (mesh.is_null()) {
return;
}
- const RID mesh_rid = get_mesh()->get_rid();
+ RID mesh_rid = mesh->get_rid();
+ if (owned_mesh != mesh_rid) {
+ _become_mesh_owner();
+ mesh_rid = mesh->get_rid();
+ PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid);
+ }
+
if (!rendering_server_handler.is_ready(mesh_rid)) {
rendering_server_handler.prepare(mesh_rid, 0);
@@ -430,11 +436,11 @@ void SoftDynamicBody3D::_draw_soft_mesh() {
rendering_server_handler.commit_changes();
}
-void SoftDynamicBody3D::prepare_physics_server() {
+void SoftDynamicBody3D::_prepare_physics_server() {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
- if (get_mesh().is_valid()) {
- PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()->get_rid());
+ if (mesh.is_valid()) {
+ PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh->get_rid());
} else {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID());
}
@@ -443,9 +449,13 @@ void SoftDynamicBody3D::prepare_physics_server() {
}
#endif
- if (get_mesh().is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) {
- become_mesh_owner();
- PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()->get_rid());
+ if (mesh.is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) {
+ RID mesh_rid = mesh->get_rid();
+ if (owned_mesh != mesh_rid) {
+ _become_mesh_owner();
+ mesh_rid = mesh->get_rid();
+ }
+ PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid);
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh));
} else {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID());
@@ -455,38 +465,32 @@ void SoftDynamicBody3D::prepare_physics_server() {
}
}
-void SoftDynamicBody3D::become_mesh_owner() {
- if (mesh.is_null()) {
- return;
- }
+void SoftDynamicBody3D::_become_mesh_owner() {
+ Vector<Ref<Material>> copy_materials;
+ copy_materials.append_array(surface_override_materials);
- if (!mesh_owner) {
- mesh_owner = true;
+ ERR_FAIL_COND(!mesh->get_surface_count());
- Vector<Ref<Material>> copy_materials;
- copy_materials.append_array(surface_override_materials);
+ // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody
+ Array surface_arrays = mesh->surface_get_arrays(0);
+ Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0);
+ Dictionary surface_lods = mesh->surface_get_lods(0);
+ uint32_t surface_format = mesh->surface_get_format(0);
- ERR_FAIL_COND(!mesh->get_surface_count());
+ surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
- // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody
- Array surface_arrays = mesh->surface_get_arrays(0);
- Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0);
- Dictionary surface_lods = mesh->surface_get_lods(0);
- uint32_t surface_format = mesh->surface_get_format(0);
+ Ref<ArrayMesh> soft_mesh;
+ soft_mesh.instantiate();
+ soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format);
+ soft_mesh->surface_set_material(0, mesh->surface_get_material(0));
- surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE;
+ set_mesh(soft_mesh);
- Ref<ArrayMesh> soft_mesh;
- soft_mesh.instantiate();
- soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format);
- soft_mesh->surface_set_material(0, mesh->surface_get_material(0));
-
- set_mesh(soft_mesh);
-
- for (int i = copy_materials.size() - 1; 0 <= i; --i) {
- set_surface_override_material(i, copy_materials[i]);
- }
+ for (int i = copy_materials.size() - 1; 0 <= i; --i) {
+ set_surface_override_material(i, copy_materials[i]);
}
+
+ owned_mesh = soft_mesh->get_rid();
}
void SoftDynamicBody3D::set_collision_mask(uint32_t p_mask) {
@@ -548,16 +552,10 @@ void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) {
return;
}
- bool inside_tree = is_inside_tree();
-
- if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
- prepare_physics_server();
- }
-
disable_mode = p_mode;
- if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
- prepare_physics_server();
+ if (mesh.is_valid() && is_inside_tree() && !is_enabled()) {
+ _prepare_physics_server();
}
}
diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h
index 5e7fbfe29e..57e116aa05 100644
--- a/scene/3d/soft_dynamic_body_3d.h
+++ b/scene/3d/soft_dynamic_body_3d.h
@@ -90,7 +90,7 @@ private:
DisableMode disable_mode = DISABLE_MODE_REMOVE;
- bool mesh_owner = false;
+ RID owned_mesh;
uint32_t collision_mask = 1;
uint32_t collision_layer = 1;
NodePath parent_collision_ignore;
@@ -106,6 +106,12 @@ private:
void _update_pickable();
+ void _update_physics_server();
+ void _draw_soft_mesh();
+
+ void _prepare_physics_server();
+ void _become_mesh_owner();
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -120,14 +126,7 @@ protected:
TypedArray<String> get_configuration_warnings() const override;
-protected:
- void _update_physics_server();
- void _draw_soft_mesh();
-
public:
- void prepare_physics_server();
- void become_mesh_owner();
-
RID get_physics_rid() const { return physics_rid; }
void set_collision_mask(uint32_t p_mask);
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 349a534680..90af70e7c2 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -743,6 +743,8 @@ void Sprite3D::_validate_property(PropertyInfo &property) const {
if (property.name == "frame_coords") {
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
+
+ SpriteBase3D::_validate_property(property);
}
void Sprite3D::_bind_methods() {
@@ -1015,6 +1017,8 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
}
property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
+
+ SpriteBase3D::_validate_property(property);
}
void AnimatedSprite3D::_notification(int p_what) {
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 90c2a309e1..61448c0e32 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -118,12 +118,6 @@ public:
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
- void set_region_enabled(bool p_region);
- bool is_region_enabled() const;
-
- void set_region_rect(const Rect2 &p_region_rect);
- Rect2 get_region_rect() const;
-
void set_modulate(const Color &p_color);
Color get_modulate() const;
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 9dbee58f0e..a16820cbdc 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -261,6 +261,8 @@ void XRNode3D::_validate_property(PropertyInfo &property) const {
}
property.hint_string = hint_string;
}
+
+ Node3D::_validate_property(property);
}
void XRNode3D::set_tracker(const StringName p_tracker_name) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 1f000d5f39..26caf826a7 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -166,6 +166,8 @@ void AnimationPlayer::_validate_property(PropertyInfo &property) const {
property.hint_string = hint;
}
+
+ Node::_validate_property(property);
}
void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index 21e309efe0..d9d88b5510 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -301,7 +301,6 @@ public:
void set_current_animation(const String &p_anim);
String get_assigned_animation() const;
void set_assigned_animation(const String &p_anim);
- void stop_all();
void set_active(bool p_active);
bool is_active() const;
bool is_valid() const;
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 21b49937a7..5abea39d20 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -57,8 +57,6 @@ public:
Vector<Input> inputs;
- real_t process_input(int p_input, real_t p_time, bool p_seek, real_t p_blend);
-
friend class AnimationTree;
struct AnimationState {
@@ -85,7 +83,6 @@ public:
State *state = nullptr;
real_t _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, real_t p_time, bool p_seek, const Vector<StringName> &p_connections);
- void _pre_update_animations(HashMap<NodePath, int> *track_map);
//all this is temporary
StringName base_path;
@@ -110,8 +107,6 @@ protected:
void _validate_property(PropertyInfo &property) const override;
- void _set_parent(Object *p_parent);
-
GDVIRTUAL0RC(Dictionary, _get_child_nodes)
GDVIRTUAL0RC(Array, _get_parameter_list)
GDVIRTUAL1RC(Ref<AnimationNode>, _get_child_by_name, StringName)
@@ -265,7 +260,6 @@ private:
AnimationNode::State state;
bool cache_valid = false;
void _node_removed(Node *p_node);
- void _caches_cleared();
void _clear_caches();
bool _update_caches(AnimationPlayer *player);
diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp
index d2fd65d3d9..5065f21604 100644
--- a/scene/audio/audio_stream_player.cpp
+++ b/scene/audio/audio_stream_player.cpp
@@ -292,6 +292,8 @@ void AudioStreamPlayer::_validate_property(PropertyInfo &property) const {
property.hint_string = options;
}
+
+ Node::_validate_property(property);
}
void AudioStreamPlayer::_bus_layout_changed() {
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/control.h b/scene/gui/control.h
index b551a2e299..02ab336ef0 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -233,9 +233,6 @@ private:
static constexpr unsigned properties_managed_by_container_count = 11;
static String properties_managed_by_container[properties_managed_by_container_count];
- // used internally
- Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform);
-
void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest);
Control *_get_focus_neighbor(Side p_side, int p_count = 0);
@@ -250,7 +247,6 @@ private:
void _update_minimum_size();
void _clear_size_warning();
- void _update_scroll();
void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]);
void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 54e7d8f960..dda1151273 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -235,6 +235,25 @@ 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() && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary().strip_escapes();
+
+ deselect();
+ set_caret_at_pixel_pos(b->get_position().x);
+ if (!paste_buffer.is_empty()) {
+ insert_text_at_caret(paste_buffer);
+
+ if (!text_changed_dirty) {
+ if (is_inside_tree()) {
+ MessageQueue::get_singleton()->push_call(this, "_text_changed");
+ }
+ text_changed_dirty = true;
+ }
+ }
+ grab_focus();
+ return;
+ }
+
if (b->get_button_index() != MOUSE_BUTTON_LEFT) {
return;
}
@@ -271,6 +290,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
selection.double_click = true;
last_dblclk = 0;
caret_column = selection.begin;
+ if (!pass && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(text);
+ }
} else if (b->is_double_click()) {
// Double-click select word.
last_dblclk = OS::get_singleton()->get_ticks_msec();
@@ -286,6 +308,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
break;
}
}
+ 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));
+ }
}
}
@@ -303,6 +328,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
update();
} else {
+ 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) {
bool press_attempt = clear_button_status.press_attempt;
clear_button_status.press_attempt = false;
@@ -1890,6 +1918,14 @@ bool LineEdit::is_virtual_keyboard_enabled() const {
return virtual_keyboard_enabled;
}
+void LineEdit::set_middle_mouse_paste_enabled(bool p_enabled) {
+ middle_mouse_paste_enabled = p_enabled;
+}
+
+bool LineEdit::is_middle_mouse_paste_enabled() const {
+ return middle_mouse_paste_enabled;
+}
+
void LineEdit::set_selecting_enabled(bool p_enabled) {
selecting_enabled = p_enabled;
@@ -2156,6 +2192,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled);
ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled);
ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &LineEdit::is_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enable"), &LineEdit::set_middle_mouse_paste_enabled);
+ ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &LineEdit::is_middle_mouse_paste_enabled);
ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &LineEdit::set_selecting_enabled);
ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &LineEdit::is_selecting_enabled);
ClassDB::bind_method(D_METHOD("set_right_icon", "icon"), &LineEdit::set_right_icon);
@@ -2211,6 +2249,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
@@ -2237,33 +2276,33 @@ void LineEdit::_ensure_menu() {
menu_dir = memnew(PopupMenu);
menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
- menu->add_child(menu_dir);
+ menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
+ menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
menu_ctl = memnew(PopupMenu);
menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
- menu->add_child(menu_ctl);
+ menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
+ menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option));
@@ -2290,12 +2329,12 @@ void LineEdit::_ensure_menu() {
menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
}
menu->add_separator();
- menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
+ menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu");
menu->add_separator();
- menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
+ menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
if (editable) {
- menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
+ menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu");
}
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 923024dd56..94179ce05b 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -126,6 +126,8 @@ private:
bool virtual_keyboard_enabled = true;
+ bool middle_mouse_paste_enabled = true;
+
Ref<Texture2D> right_icon;
struct Selection {
@@ -187,7 +189,6 @@ private:
void _toggle_draw_caret();
void clear_internal();
- void changed_internal();
void _editor_settings_changed();
@@ -318,6 +319,9 @@ public:
void set_virtual_keyboard_enabled(bool p_enable);
bool is_virtual_keyboard_enabled() const;
+ void set_middle_mouse_paste_enabled(bool p_enabled);
+ bool is_middle_mouse_paste_enabled() const;
+
void set_selecting_enabled(bool p_enabled);
bool is_selecting_enabled() const;
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index c7090e7231..8458a75eef 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -80,7 +80,6 @@ protected:
virtual Size2 _get_contents_minimum_size() const override;
public:
- void set_child_rect(Control *p_child);
PopupPanel();
};
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 93d1eb5ba4..31767dd263 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1596,12 +1596,18 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
selection.to_char = words[i + 1];
selection.active = true;
+ 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 && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
selection.click_item = nullptr;
if (!b->is_double_click() && !scroll_updated) {
@@ -1719,6 +1725,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
swap = true;
} else if (selection.from_char == selection.to_char) {
selection.active = false;
+ update();
return;
}
}
@@ -2810,12 +2817,12 @@ bool RichTextLabel::is_scroll_following() const {
return scroll_follow;
}
-Error RichTextLabel::parse_bbcode(const String &p_bbcode) {
+void RichTextLabel::parse_bbcode(const String &p_bbcode) {
clear();
- return append_text(p_bbcode);
+ append_text(p_bbcode);
}
-Error RichTextLabel::append_text(const String &p_bbcode) {
+void RichTextLabel::append_text(const String &p_bbcode) {
int pos = 0;
List<String> tag_stack;
@@ -3538,8 +3545,6 @@ Error RichTextLabel::append_text(const String &p_bbcode) {
break;
}
}
-
- return OK;
}
void RichTextLabel::scroll_to_paragraph(int p_paragraph) {
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 94f02a3989..48186ca8b8 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -552,8 +552,8 @@ public:
String get_selected_text() const;
void selection_copy();
- Error parse_bbcode(const String &p_bbcode);
- Error append_text(const String &p_bbcode);
+ void parse_bbcode(const String &p_bbcode);
+ void append_text(const String &p_bbcode);
void set_use_bbcode(bool p_enable);
bool is_using_bbcode() const;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tab_bar.cpp
index 0755a79eee..78b58c773a 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* tabs.cpp */
+/* tab_bar.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "tabs.h"
+#include "tab_bar.h"
#include "core/object/message_queue.h"
#include "core/string/translation.h"
@@ -37,7 +37,7 @@
#include "scene/gui/label.h"
#include "scene/gui/texture_rect.h"
-Size2 Tabs::get_minimum_size() const {
+Size2 TabBar::get_minimum_size() const {
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
@@ -90,7 +90,7 @@ Size2 Tabs::get_minimum_size() const {
return ms;
}
-void Tabs::gui_input(const Ref<InputEvent> &p_event) {
+void TabBar::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventMouseMotion> mm = p_event;
@@ -164,7 +164,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (rb_hover != -1) {
- //pressed
+ // pressed
emit_signal(SNAME("tab_rmb_clicked"), rb_hover);
}
@@ -174,7 +174,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) {
if (cb_hover != -1) {
- //pressed
+ // pressed
emit_signal(SNAME("tab_closed"), cb_hover);
}
@@ -222,6 +222,11 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
}
}
+ if (max_drawn_tab <= 0) {
+ // Return early if there are no actual tabs to handle input for.
+ return;
+ }
+
int found = -1;
for (int i = offset; i <= max_drawn_tab; i++) {
if (tabs[i].rb_rect.has_point(pos)) {
@@ -252,7 +257,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) {
}
}
-void Tabs::_shape(int p_tab) {
+void TabBar::_shape(int p_tab) {
Ref<Font> font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size"));
@@ -268,7 +273,7 @@ void Tabs::_shape(int p_tab) {
tabs.write[p_tab].text_buf->add_string(tabs.write[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, (tabs[p_tab].language != "") ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale());
}
-void Tabs::_notification(int p_what) {
+void TabBar::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
_update_cache();
@@ -505,11 +510,11 @@ void Tabs::_notification(int p_what) {
}
}
-int Tabs::get_tab_count() const {
+int TabBar::get_tab_count() const {
return tabs.size();
}
-void Tabs::set_current_tab(int p_current) {
+void TabBar::set_current_tab(int p_current) {
if (current == p_current) {
return;
}
@@ -524,27 +529,27 @@ void Tabs::set_current_tab(int p_current) {
emit_signal(SNAME("tab_changed"), p_current);
}
-int Tabs::get_current_tab() const {
+int TabBar::get_current_tab() const {
return current;
}
-int Tabs::get_previous_tab() const {
+int TabBar::get_previous_tab() const {
return previous;
}
-int Tabs::get_hovered_tab() const {
+int TabBar::get_hovered_tab() const {
return hover;
}
-int Tabs::get_tab_offset() const {
+int TabBar::get_tab_offset() const {
return offset;
}
-bool Tabs::get_offset_buttons_visible() const {
+bool TabBar::get_offset_buttons_visible() const {
return buttons_visible;
}
-void Tabs::set_tab_title(int p_tab, const String &p_title) {
+void TabBar::set_tab_title(int p_tab, const String &p_title) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].text = p_title;
_shape(p_tab);
@@ -552,12 +557,12 @@ void Tabs::set_tab_title(int p_tab, const String &p_title) {
minimum_size_changed();
}
-String Tabs::get_tab_title(int p_tab) const {
+String TabBar::get_tab_title(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), "");
return tabs[p_tab].text;
}
-void Tabs::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direction) {
+void TabBar::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direction) {
ERR_FAIL_INDEX(p_tab, tabs.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (tabs[p_tab].text_direction != p_text_direction) {
@@ -567,19 +572,19 @@ void Tabs::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direc
}
}
-Control::TextDirection Tabs::get_tab_text_direction(int p_tab) const {
+Control::TextDirection TabBar::get_tab_text_direction(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Control::TEXT_DIRECTION_INHERITED);
return tabs[p_tab].text_direction;
}
-void Tabs::clear_tab_opentype_features(int p_tab) {
+void TabBar::clear_tab_opentype_features(int p_tab) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].opentype_features.clear();
_shape(p_tab);
update();
}
-void Tabs::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) {
+void TabBar::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_tab, tabs.size());
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag) || (int)tabs[p_tab].opentype_features[tag] != p_value) {
@@ -589,7 +594,7 @@ void Tabs::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value
}
}
-int Tabs::get_tab_opentype_feature(int p_tab, const String &p_name) const {
+int TabBar::get_tab_opentype_feature(int p_tab, const String &p_name) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!tabs[p_tab].opentype_features.has(tag)) {
@@ -598,7 +603,7 @@ int Tabs::get_tab_opentype_feature(int p_tab, const String &p_name) const {
return tabs[p_tab].opentype_features[tag];
}
-void Tabs::set_tab_language(int p_tab, const String &p_language) {
+void TabBar::set_tab_language(int p_tab, const String &p_language) {
ERR_FAIL_INDEX(p_tab, tabs.size());
if (tabs[p_tab].language != p_language) {
tabs.write[p_tab].language = p_language;
@@ -607,35 +612,35 @@ void Tabs::set_tab_language(int p_tab, const String &p_language) {
}
}
-String Tabs::get_tab_language(int p_tab) const {
+String TabBar::get_tab_language(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), "");
return tabs[p_tab].language;
}
-void Tabs::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
+void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].icon = p_icon;
update();
minimum_size_changed();
}
-Ref<Texture2D> Tabs::get_tab_icon(int p_tab) const {
+Ref<Texture2D> TabBar::get_tab_icon(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Ref<Texture2D>());
return tabs[p_tab].icon;
}
-void Tabs::set_tab_disabled(int p_tab, bool p_disabled) {
+void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].disabled = p_disabled;
update();
}
-bool Tabs::get_tab_disabled(int p_tab) const {
+bool TabBar::get_tab_disabled(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), false);
return tabs[p_tab].disabled;
}
-void Tabs::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) {
+void TabBar::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) {
ERR_FAIL_INDEX(p_tab, tabs.size());
tabs.write[p_tab].right_button = p_right_button;
_update_cache();
@@ -643,12 +648,12 @@ void Tabs::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button)
minimum_size_changed();
}
-Ref<Texture2D> Tabs::get_tab_right_button(int p_tab) const {
+Ref<Texture2D> TabBar::get_tab_right_button(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Ref<Texture2D>());
return tabs[p_tab].right_button;
}
-void Tabs::_update_hover() {
+void TabBar::_update_hover() {
if (!is_inside_tree()) {
return;
}
@@ -685,7 +690,7 @@ void Tabs::_update_hover() {
}
}
-void Tabs::_update_cache() {
+void TabBar::_update_cache() {
Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled"));
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected"));
@@ -748,7 +753,7 @@ void Tabs::_update_cache() {
}
}
-void Tabs::_on_mouse_exited() {
+void TabBar::_on_mouse_exited() {
rb_hover = -1;
cb_hover = -1;
hover = -1;
@@ -756,7 +761,7 @@ void Tabs::_on_mouse_exited() {
update();
}
-void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
+void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
Tab t;
t.text = p_str;
t.xl_text = atr(p_str);
@@ -775,7 +780,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
minimum_size_changed();
}
-void Tabs::clear_tabs() {
+void TabBar::clear_tabs() {
tabs.clear();
current = 0;
previous = 0;
@@ -783,7 +788,7 @@ void Tabs::clear_tabs() {
update();
}
-void Tabs::remove_tab(int p_idx) {
+void TabBar::remove_tab(int p_idx) {
ERR_FAIL_INDEX(p_idx, tabs.size());
tabs.remove(p_idx);
if (current >= p_idx) {
@@ -805,7 +810,7 @@ void Tabs::remove_tab(int p_idx) {
_ensure_no_over_offset();
}
-Variant Tabs::get_drag_data(const Point2 &p_point) {
+Variant TabBar::get_drag_data(const Point2 &p_point) {
if (!drag_to_rearrange_enabled) {
return Variant();
}
@@ -839,7 +844,7 @@ Variant Tabs::get_drag_data(const Point2 &p_point) {
return drag_data;
}
-bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
+bool TabBar::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
if (!drag_to_rearrange_enabled) {
return false;
}
@@ -855,9 +860,9 @@ bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
if (from_path == to_path) {
return true;
} else if (get_tabs_rearrange_group() != -1) {
- // drag and drop between other Tabs
+ // drag and drop between other TabBars
Node *from_node = get_node(from_path);
- Tabs *from_tabs = Object::cast_to<Tabs>(from_node);
+ TabBar *from_tabs = Object::cast_to<TabBar>(from_node);
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
return true;
}
@@ -866,7 +871,7 @@ bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
return false;
}
-void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
+void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) {
if (!drag_to_rearrange_enabled) {
return;
}
@@ -892,7 +897,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
} else if (get_tabs_rearrange_group() != -1) {
// drag and drop between Tabs
Node *from_node = get_node(from_path);
- Tabs *from_tabs = Object::cast_to<Tabs>(from_node);
+ TabBar *from_tabs = Object::cast_to<TabBar>(from_node);
if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) {
if (tab_from_id >= from_tabs->get_tab_count()) {
return;
@@ -912,7 +917,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) {
update();
}
-int Tabs::get_tab_idx_at_point(const Point2 &p_point) const {
+int TabBar::get_tab_idx_at_point(const Point2 &p_point) const {
int hover_now = -1;
for (int i = offset; i <= max_drawn_tab; i++) {
Rect2 rect = get_tab_rect(i);
@@ -924,17 +929,17 @@ int Tabs::get_tab_idx_at_point(const Point2 &p_point) const {
return hover_now;
}
-void Tabs::set_tab_align(TabAlign p_align) {
+void TabBar::set_tab_align(TabAlign p_align) {
ERR_FAIL_INDEX(p_align, ALIGN_MAX);
tab_align = p_align;
update();
}
-Tabs::TabAlign Tabs::get_tab_align() const {
+TabBar::TabAlign TabBar::get_tab_align() const {
return tab_align;
}
-void Tabs::set_clip_tabs(bool p_clip_tabs) {
+void TabBar::set_clip_tabs(bool p_clip_tabs) {
if (clip_tabs == p_clip_tabs) {
return;
}
@@ -943,11 +948,11 @@ void Tabs::set_clip_tabs(bool p_clip_tabs) {
minimum_size_changed();
}
-bool Tabs::get_clip_tabs() const {
+bool TabBar::get_clip_tabs() const {
return clip_tabs;
}
-void Tabs::move_tab(int from, int to) {
+void TabBar::move_tab(int from, int to) {
if (from == to) {
return;
}
@@ -963,7 +968,7 @@ void Tabs::move_tab(int from, int to) {
update();
}
-int Tabs::get_tab_width(int p_idx) const {
+int TabBar::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected"));
@@ -1005,7 +1010,7 @@ int Tabs::get_tab_width(int p_idx) const {
return x;
}
-void Tabs::_ensure_no_over_offset() {
+void TabBar::_ensure_no_over_offset() {
if (!is_inside_tree()) {
return;
}
@@ -1031,7 +1036,7 @@ void Tabs::_ensure_no_over_offset() {
}
}
-void Tabs::ensure_tab_visible(int p_idx) {
+void TabBar::ensure_tab_visible(int p_idx) {
if (!is_inside_tree()) {
return;
}
@@ -1068,7 +1073,7 @@ void Tabs::ensure_tab_visible(int p_idx) {
}
}
-Rect2 Tabs::get_tab_rect(int p_tab) const {
+Rect2 TabBar::get_tab_rect(int p_tab) const {
ERR_FAIL_INDEX_V(p_tab, tabs.size(), Rect2());
if (is_layout_rtl()) {
return Rect2(get_size().width - tabs[p_tab].ofs_cache - tabs[p_tab].size_cache, 0, tabs[p_tab].size_cache, get_size().height);
@@ -1077,93 +1082,93 @@ Rect2 Tabs::get_tab_rect(int p_tab) const {
}
}
-void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
+void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX);
cb_displaypolicy = p_policy;
update();
}
-Tabs::CloseButtonDisplayPolicy Tabs::get_tab_close_display_policy() const {
+TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const {
return cb_displaypolicy;
}
-void Tabs::set_min_width(int p_width) {
+void TabBar::set_min_width(int p_width) {
min_width = p_width;
}
-void Tabs::set_scrolling_enabled(bool p_enabled) {
+void TabBar::set_scrolling_enabled(bool p_enabled) {
scrolling_enabled = p_enabled;
}
-bool Tabs::get_scrolling_enabled() const {
+bool TabBar::get_scrolling_enabled() const {
return scrolling_enabled;
}
-void Tabs::set_drag_to_rearrange_enabled(bool p_enabled) {
+void TabBar::set_drag_to_rearrange_enabled(bool p_enabled) {
drag_to_rearrange_enabled = p_enabled;
}
-bool Tabs::get_drag_to_rearrange_enabled() const {
+bool TabBar::get_drag_to_rearrange_enabled() const {
return drag_to_rearrange_enabled;
}
-void Tabs::set_tabs_rearrange_group(int p_group_id) {
+void TabBar::set_tabs_rearrange_group(int p_group_id) {
tabs_rearrange_group = p_group_id;
}
-int Tabs::get_tabs_rearrange_group() const {
+int TabBar::get_tabs_rearrange_group() const {
return tabs_rearrange_group;
}
-void Tabs::set_select_with_rmb(bool p_enabled) {
+void TabBar::set_select_with_rmb(bool p_enabled) {
select_with_rmb = p_enabled;
}
-bool Tabs::get_select_with_rmb() const {
+bool TabBar::get_select_with_rmb() const {
return select_with_rmb;
}
-void Tabs::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_update_hover"), &Tabs::_update_hover);
- ClassDB::bind_method(D_METHOD("get_tab_count"), &Tabs::get_tab_count);
- ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &Tabs::set_current_tab);
- ClassDB::bind_method(D_METHOD("get_current_tab"), &Tabs::get_current_tab);
- ClassDB::bind_method(D_METHOD("get_previous_tab"), &Tabs::get_previous_tab);
- ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &Tabs::set_tab_title);
- ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &Tabs::get_tab_title);
- ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &Tabs::set_tab_text_direction);
- ClassDB::bind_method(D_METHOD("get_tab_text_direction", "tab_idx"), &Tabs::get_tab_text_direction);
- ClassDB::bind_method(D_METHOD("set_tab_opentype_feature", "tab_idx", "tag", "values"), &Tabs::set_tab_opentype_feature);
- ClassDB::bind_method(D_METHOD("get_tab_opentype_feature", "tab_idx", "tag"), &Tabs::get_tab_opentype_feature);
- ClassDB::bind_method(D_METHOD("clear_tab_opentype_features", "tab_idx"), &Tabs::clear_tab_opentype_features);
- ClassDB::bind_method(D_METHOD("set_tab_language", "tab_idx", "language"), &Tabs::set_tab_language);
- ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &Tabs::get_tab_language);
- ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &Tabs::set_tab_icon);
- ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &Tabs::get_tab_icon);
- ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled);
- ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled);
- ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &Tabs::remove_tab);
- ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>()));
- ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align);
- ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align);
- ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &Tabs::set_clip_tabs);
- ClassDB::bind_method(D_METHOD("get_clip_tabs"), &Tabs::get_clip_tabs);
- ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset);
- ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible);
- ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible);
- ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect);
- ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab);
- ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy);
- ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy);
- ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled);
- ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled);
- ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &Tabs::set_drag_to_rearrange_enabled);
- ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &Tabs::get_drag_to_rearrange_enabled);
- ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &Tabs::set_tabs_rearrange_group);
- ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &Tabs::get_tabs_rearrange_group);
-
- ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &Tabs::set_select_with_rmb);
- ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &Tabs::get_select_with_rmb);
+void TabBar::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_hover"), &TabBar::_update_hover);
+ ClassDB::bind_method(D_METHOD("get_tab_count"), &TabBar::get_tab_count);
+ ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabBar::set_current_tab);
+ ClassDB::bind_method(D_METHOD("get_current_tab"), &TabBar::get_current_tab);
+ ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabBar::get_previous_tab);
+ ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabBar::set_tab_title);
+ ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabBar::get_tab_title);
+ ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &TabBar::set_tab_text_direction);
+ ClassDB::bind_method(D_METHOD("get_tab_text_direction", "tab_idx"), &TabBar::get_tab_text_direction);
+ ClassDB::bind_method(D_METHOD("set_tab_opentype_feature", "tab_idx", "tag", "values"), &TabBar::set_tab_opentype_feature);
+ ClassDB::bind_method(D_METHOD("get_tab_opentype_feature", "tab_idx", "tag"), &TabBar::get_tab_opentype_feature);
+ ClassDB::bind_method(D_METHOD("clear_tab_opentype_features", "tab_idx"), &TabBar::clear_tab_opentype_features);
+ ClassDB::bind_method(D_METHOD("set_tab_language", "tab_idx", "language"), &TabBar::set_tab_language);
+ ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &TabBar::get_tab_language);
+ ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabBar::set_tab_icon);
+ ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabBar::get_tab_icon);
+ ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabBar::set_tab_disabled);
+ ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabBar::get_tab_disabled);
+ ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &TabBar::remove_tab);
+ ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &TabBar::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>()));
+ ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &TabBar::set_tab_align);
+ ClassDB::bind_method(D_METHOD("get_tab_align"), &TabBar::get_tab_align);
+ ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &TabBar::set_clip_tabs);
+ ClassDB::bind_method(D_METHOD("get_clip_tabs"), &TabBar::get_clip_tabs);
+ ClassDB::bind_method(D_METHOD("get_tab_offset"), &TabBar::get_tab_offset);
+ ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &TabBar::get_offset_buttons_visible);
+ ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &TabBar::ensure_tab_visible);
+ ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &TabBar::get_tab_rect);
+ ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &TabBar::move_tab);
+ ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &TabBar::set_tab_close_display_policy);
+ ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &TabBar::get_tab_close_display_policy);
+ ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &TabBar::set_scrolling_enabled);
+ ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &TabBar::get_scrolling_enabled);
+ ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabBar::set_drag_to_rearrange_enabled);
+ ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &TabBar::get_drag_to_rearrange_enabled);
+ ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &TabBar::set_tabs_rearrange_group);
+ ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabBar::get_tabs_rearrange_group);
+
+ ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &TabBar::set_select_with_rmb);
+ ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &TabBar::get_select_with_rmb);
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_rmb_clicked", PropertyInfo(Variant::INT, "tab")));
@@ -1190,6 +1195,6 @@ void Tabs::_bind_methods() {
BIND_ENUM_CONSTANT(CLOSE_BUTTON_MAX);
}
-Tabs::Tabs() {
- connect("mouse_exited", callable_mp(this, &Tabs::_on_mouse_exited));
+TabBar::TabBar() {
+ connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited));
}
diff --git a/scene/gui/tabs.h b/scene/gui/tab_bar.h
index b044453803..411a62b1d9 100644
--- a/scene/gui/tabs.h
+++ b/scene/gui/tab_bar.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* tabs.h */
+/* tab_bar.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef TABS_H
-#define TABS_H
+#ifndef TAB_BAR_H
+#define TAB_BAR_H
#include "scene/gui/control.h"
#include "scene/resources/text_line.h"
-class Tabs : public Control {
- GDCLASS(Tabs, Control);
+class TabBar : public Control {
+ GDCLASS(TabBar, Control);
public:
enum TabAlign {
@@ -83,7 +83,6 @@ private:
Vector<Tab> tabs;
int current = 0;
int previous = 0;
- int _get_top_margin() const;
TabAlign tab_align = ALIGN_CENTER;
bool clip_tabs = true;
int rb_hover = -1;
@@ -187,10 +186,10 @@ public:
Rect2 get_tab_rect(int p_tab) const;
Size2 get_minimum_size() const override;
- Tabs();
+ TabBar();
};
-VARIANT_ENUM_CAST(Tabs::TabAlign);
-VARIANT_ENUM_CAST(Tabs::CloseButtonDisplayPolicy);
+VARIANT_ENUM_CAST(TabBar::TabAlign);
+VARIANT_ENUM_CAST(TabBar::CloseButtonDisplayPolicy);
-#endif // TABS_H
+#endif // TAB_BAR_H
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 55c18980f9..8cb3b23020 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1534,6 +1534,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
update();
}
+ 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();
+ }
+
if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) {
_reset_caret_blink_timer();
@@ -1571,6 +1575,9 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
dragging_selection = false;
can_drag_minimap = false;
click_select_held->stop();
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
}
// Notify to show soft keyboard.
@@ -2596,6 +2603,14 @@ bool TextEdit::is_virtual_keyboard_enabled() const {
return virtual_keyboard_enabled;
}
+void TextEdit::set_middle_mouse_paste_enabled(bool p_enabled) {
+ middle_mouse_paste_enabled = p_enabled;
+}
+
+bool TextEdit::is_middle_mouse_paste_enabled() const {
+ return middle_mouse_paste_enabled;
+}
+
// Text manipulation
void TextEdit::clear() {
setting_text = true;
@@ -2915,6 +2930,13 @@ void TextEdit::paste() {
_paste_internal();
}
+void TextEdit::paste_primary_clipboard() {
+ if (GDVIRTUAL_CALL(_paste_primary_clipboard)) {
+ return;
+ }
+ _paste_primary_clipboard_internal();
+}
+
// Context menu.
PopupMenu *TextEdit::get_menu() const {
const_cast<TextEdit *>(this)->_generate_context_menu();
@@ -4536,6 +4558,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enabled"), &TextEdit::set_virtual_keyboard_enabled);
ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &TextEdit::is_virtual_keyboard_enabled);
+ ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enabled"), &TextEdit::set_middle_mouse_paste_enabled);
+ ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &TextEdit::is_middle_mouse_paste_enabled);
+
// Text manipulation
ClassDB::bind_method(D_METHOD("clear"), &TextEdit::clear);
@@ -4575,6 +4600,7 @@ void TextEdit::_bind_methods() {
GDVIRTUAL_BIND(_cut)
GDVIRTUAL_BIND(_copy)
GDVIRTUAL_BIND(_paste)
+ GDVIRTUAL_BIND(_paste_primary_clipboard)
// Context Menu
BIND_ENUM_CONSTANT(MENU_CUT);
@@ -4850,6 +4876,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
@@ -5141,6 +5168,24 @@ void TextEdit::_paste_internal() {
end_complex_operation();
}
+void TextEdit::_paste_primary_clipboard_internal() {
+ if (!is_editable() || !DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ return;
+ }
+
+ String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary();
+
+ Point2i pos = get_line_column_at_pos(get_local_mouse_pos());
+ deselect();
+ set_caret_line(pos.y, true, false);
+ set_caret_column(pos.x);
+ if (!paste_buffer.is_empty()) {
+ insert_text_at_caret(paste_buffer);
+ }
+
+ grab_focus();
+}
+
/* Text. */
// Context menu.
void TextEdit::_generate_context_menu() {
@@ -5150,32 +5195,32 @@ void TextEdit::_generate_context_menu() {
menu_dir = memnew(PopupMenu);
menu_dir->set_name("DirMenu");
- menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED);
- menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO);
- menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR);
- menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL);
+ menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED);
+ menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO);
+ menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR);
+ menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL);
menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT);
menu_ctl = memnew(PopupMenu);
menu_ctl->set_name("CTLMenu");
- menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM);
- menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM);
- menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE);
- menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE);
- menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO);
- menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO);
- menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF);
+ menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM);
+ menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE);
+ menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO);
+ menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO);
+ menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF);
menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM);
- menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI);
- menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI);
- menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI);
- menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI);
+ menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM);
+ menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI);
+ menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI);
+ menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI);
+ menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI);
menu_ctl->add_separator();
- menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ);
- menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
- menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ);
- menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY);
+ menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ);
+ menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ);
+ menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ);
+ menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY);
menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT);
menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option));
@@ -5203,12 +5248,12 @@ void TextEdit::_generate_context_menu() {
menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0);
}
menu->add_separator();
- menu->add_submenu_item(RTR("Text writing direction"), "DirMenu");
+ menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu");
menu->add_separator();
- menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC);
+ menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars);
if (editable) {
- menu->add_submenu_item(RTR("Insert control character"), "CTLMenu");
+ menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu");
}
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED);
menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO);
@@ -5477,6 +5522,10 @@ void TextEdit::_update_selection_mode_word() {
}
}
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
+
update();
click_select_held->start();
@@ -5504,6 +5553,10 @@ void TextEdit::_update_selection_mode_line() {
set_caret_column(0);
select(selection.selecting_line, selection.selecting_column, line, col);
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) {
+ DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text());
+ }
+
update();
click_select_held->start();
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 16c1ee9ff9..8823e44c0d 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -269,6 +269,7 @@ private:
bool context_menu_enabled = true;
bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
+ bool middle_mouse_paste_enabled = true;
// Overridable actions
String cut_copy_line = "";
@@ -586,12 +587,14 @@ protected:
virtual void _cut_internal();
virtual void _copy_internal();
virtual void _paste_internal();
+ virtual void _paste_primary_clipboard_internal();
GDVIRTUAL1(_handle_unicode_input, int)
GDVIRTUAL0(_backspace)
GDVIRTUAL0(_cut)
GDVIRTUAL0(_copy)
GDVIRTUAL0(_paste)
+ GDVIRTUAL0(_paste_primary_clipboard)
public:
/* General overrides. */
@@ -640,6 +643,9 @@ public:
void set_virtual_keyboard_enabled(bool p_enabled);
bool is_virtual_keyboard_enabled() const;
+ void set_middle_mouse_paste_enabled(bool p_enabled);
+ bool is_middle_mouse_paste_enabled() const;
+
// Text manipulation
void clear();
@@ -674,6 +680,7 @@ public:
void cut();
void copy();
void paste();
+ void paste_primary_clipboard();
// Context menu.
PopupMenu *get_menu() const;
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/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp
index 4540e42b4c..26bff4494b 100644
--- a/scene/main/canvas_layer.cpp
+++ b/scene/main/canvas_layer.cpp
@@ -128,7 +128,7 @@ void CanvasLayer::_notification(int p_what) {
} else {
vp = Node::get_viewport();
}
- ERR_FAIL_COND(!vp);
+ ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized.");
vp->_canvas_layer_add(this);
viewport = vp->get_viewport_rid();
@@ -140,6 +140,8 @@ void CanvasLayer::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
+ ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized.");
+
vp->_canvas_layer_remove(this);
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
viewport = RID();
@@ -160,6 +162,8 @@ Size2 CanvasLayer::get_viewport_size() const {
return Size2(1, 1);
}
+ ERR_FAIL_NULL_V_MSG(vp, Size2(1, 1), "Viewport is not initialized.");
+
Rect2 r = vp->get_visible_rect();
return r.size;
}
@@ -169,7 +173,7 @@ RID CanvasLayer::get_viewport() const {
}
void CanvasLayer::set_custom_viewport(Node *p_viewport) {
- ERR_FAIL_NULL(p_viewport);
+ ERR_FAIL_NULL_MSG(p_viewport, "Cannot set viewport to nullptr.");
if (is_inside_tree()) {
vp->_canvas_layer_remove(this);
RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas);
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 19331c1906..7a4f9f9c52 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -136,7 +136,6 @@ private:
void _flush_ugc();
_FORCE_INLINE_ void _update_group_order(Group &g, bool p_use_priority = false);
- void _update_listener();
Array _get_nodes_in_group(const StringName &p_group);
@@ -265,9 +264,6 @@ public:
void set_pause(bool p_enabled);
bool is_paused() const;
- void set_camera(const RID &p_camera);
- RID get_camera() const;
-
#ifdef DEBUG_ENABLED
void set_debug_collisions_hint(bool p_enabled);
bool is_debugging_collisions_hint() const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 0e62e6e30a..3280190250 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2192,7 +2192,10 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
if (physics_object_over.is_valid()) {
CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
if (co) {
- if (!(p_paused_only && co->can_process())) {
+ if (!co->is_inside_tree()) {
+ physics_object_over = ObjectID();
+ physics_object_capture = ObjectID();
+ } else if (!(p_paused_only && co->can_process())) {
co->_mouse_exit();
physics_object_over = ObjectID();
physics_object_capture = ObjectID();
@@ -2213,7 +2216,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus
Object *o = ObjectDB::get_instance(E->key());
if (o) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
+ if (co && co->is_inside_tree()) {
if (p_clean_all_frames && p_paused_only && co->can_process()) {
continue;
}
@@ -2239,7 +2242,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus
Object *o = ObjectDB::get_instance(E->key().first);
if (o) {
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
- if (co) {
+ if (co && co->is_inside_tree()) {
if (p_clean_all_frames && p_paused_only && co->can_process()) {
continue;
}
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 61c25ae9db..33e0e2cad7 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -115,8 +115,8 @@
#include "scene/gui/spin_box.h"
#include "scene/gui/split_container.h"
#include "scene/gui/subviewport_container.h"
+#include "scene/gui/tab_bar.h"
#include "scene/gui/tab_container.h"
-#include "scene/gui/tabs.h"
#include "scene/gui/text_edit.h"
#include "scene/gui/texture_button.h"
#include "scene/gui/texture_progress_bar.h"
@@ -262,7 +262,7 @@ static Ref<ResourceFormatLoaderShader> resource_loader_shader;
void register_scene_types() {
SceneStringNames::create();
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
Node::init_node_hrcr();
@@ -287,7 +287,7 @@ void register_scene_types() {
resource_loader_shader.instantiate();
ResourceLoader::add_resource_format_loader(resource_loader_shader, true);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(Object);
@@ -309,7 +309,7 @@ void register_scene_types() {
GDREGISTER_CLASS(ButtonGroup);
GDREGISTER_VIRTUAL_CLASS(BaseButton);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(Control);
GDREGISTER_CLASS(Button);
@@ -330,7 +330,7 @@ void register_scene_types() {
GDREGISTER_CLASS(Panel);
GDREGISTER_VIRTUAL_CLASS(Range);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(TextureRect);
GDREGISTER_CLASS(ColorRect);
@@ -338,7 +338,7 @@ void register_scene_types() {
GDREGISTER_CLASS(ReferenceRect);
GDREGISTER_CLASS(AspectRatioContainer);
GDREGISTER_CLASS(TabContainer);
- GDREGISTER_CLASS(Tabs);
+ GDREGISTER_CLASS(TabBar);
GDREGISTER_VIRTUAL_CLASS(Separator);
GDREGISTER_CLASS(HSeparator);
GDREGISTER_CLASS(VSeparator);
@@ -352,7 +352,7 @@ void register_scene_types() {
GDREGISTER_CLASS(ScrollContainer);
GDREGISTER_CLASS(PanelContainer);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(TextureProgressBar);
GDREGISTER_CLASS(ItemList);
@@ -391,7 +391,7 @@ void register_scene_types() {
GDREGISTER_CLASS(GraphNode);
GDREGISTER_CLASS(GraphEdit);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
bool swap_cancel_ok = false;
if (DisplayServer::get_singleton()) {
@@ -431,9 +431,9 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimationNodeTimeSeek);
GDREGISTER_CLASS(AnimationNodeTransition);
- GDREGISTER_CLASS(ShaderGlobalsOverride); //can be used in any shader
+ GDREGISTER_CLASS(ShaderGlobalsOverride); // can be used in any shader
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
/* REGISTER 3D */
@@ -486,9 +486,9 @@ void register_scene_types() {
GDREGISTER_CLASS(Position3D);
GDREGISTER_CLASS(RootMotionView);
- ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor
+ ClassDB::set_class_enabled("RootMotionView", false); // disabled by default, enabled by editor
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
@@ -533,7 +533,7 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationAgent3D);
GDREGISTER_CLASS(NavigationObstacle3D);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
#endif
/* REGISTER SHADER */
@@ -673,7 +673,7 @@ void register_scene_types() {
GDREGISTER_CLASS(OccluderPolygon2D);
GDREGISTER_CLASS(BackBufferCopy);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(Camera2D);
GDREGISTER_CLASS(AudioListener2D);
@@ -705,7 +705,7 @@ void register_scene_types() {
GDREGISTER_CLASS(PhysicalBone2D);
GDREGISTER_CLASS(SkeletonModification2DPhysicalBones);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
/* REGISTER RESOURCES */
@@ -746,7 +746,7 @@ void register_scene_types() {
GDREGISTER_CLASS(MeshLibrary);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_VIRTUAL_CLASS(Shape3D);
GDREGISTER_CLASS(SeparationRayShape3D);
@@ -768,7 +768,7 @@ void register_scene_types() {
ClassDB::register_class<SkeletonModification3DTwoBoneIK>();
ClassDB::register_class<SkeletonModification3DStackHolder>();
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(VelocityTracker3D);
#endif
@@ -823,7 +823,7 @@ void register_scene_types() {
GDREGISTER_CLASS(BitMap);
GDREGISTER_CLASS(Gradient);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_CLASS(AudioStreamPlayer);
GDREGISTER_CLASS(AudioStreamPlayer2D);
@@ -833,7 +833,7 @@ void register_scene_types() {
GDREGISTER_VIRTUAL_CLASS(VideoStream);
GDREGISTER_CLASS(AudioStreamSample);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_VIRTUAL_CLASS(Shape2D);
GDREGISTER_CLASS(WorldBoundaryShape2D);
@@ -854,13 +854,13 @@ void register_scene_types() {
GDREGISTER_CLASS(NavigationAgent2D);
GDREGISTER_CLASS(NavigationObstacle2D);
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
GDREGISTER_VIRTUAL_CLASS(SceneState);
GDREGISTER_CLASS(PackedScene);
GDREGISTER_CLASS(SceneTree);
- GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); //sorry, you can't create it
+ GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); // sorry, you can't create it
#ifndef DISABLE_DEPRECATED
// Dropped in 4.0, near approximation.
@@ -1008,7 +1008,7 @@ void register_scene_types() {
#endif /* DISABLE_DEPRECATED */
- OS::get_singleton()->yield(); //may take time to init
+ OS::get_singleton()->yield(); // may take time to init
for (int i = 0; i < 20; i++) {
GLOBAL_DEF_BASIC(vformat("layer_names/2d_render/layer_%d", i + 1), "");
@@ -1086,7 +1086,7 @@ void unregister_scene_types() {
ResourceLoader::remove_resource_format_loader(resource_loader_shader);
resource_loader_shader.unref();
- //StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either
+ // StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either
#ifndef _3D_DISABLED
BaseMaterial3D::finish_shaders();
#endif // _3D_DISABLED
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 54bb7a82cf..ed093d7ea3 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -785,30 +785,30 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("icon_separation", "TabContainer", 4 * scale);
theme->set_constant("outline_size", "TabContainer", 0);
- // Tabs
+ // TabBar
- theme->set_stylebox("tab_selected", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2));
- theme->set_stylebox("tab_unselected", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3));
- theme->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3));
- theme->set_stylebox("close_bg_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4));
- theme->set_stylebox("close_bg_highlight", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4));
+ theme->set_stylebox("tab_selected", "TabBar", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2));
+ theme->set_stylebox("tab_unselected", "TabBar", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3));
+ theme->set_stylebox("tab_disabled", "TabBar", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3));
+ theme->set_stylebox("close_bg_pressed", "TabBar", make_stylebox(button_pressed_png, 4, 4, 4, 4));
+ theme->set_stylebox("close_bg_highlight", "TabBar", make_stylebox(button_normal_png, 4, 4, 4, 4));
- theme->set_icon("increment", "Tabs", make_icon(scroll_button_right_png));
- theme->set_icon("increment_highlight", "Tabs", make_icon(scroll_button_right_hl_png));
- theme->set_icon("decrement", "Tabs", make_icon(scroll_button_left_png));
- theme->set_icon("decrement_highlight", "Tabs", make_icon(scroll_button_left_hl_png));
- theme->set_icon("close", "Tabs", make_icon(tab_close_png));
+ theme->set_icon("increment", "TabBar", make_icon(scroll_button_right_png));
+ theme->set_icon("increment_highlight", "TabBar", make_icon(scroll_button_right_hl_png));
+ theme->set_icon("decrement", "TabBar", make_icon(scroll_button_left_png));
+ theme->set_icon("decrement_highlight", "TabBar", make_icon(scroll_button_left_hl_png));
+ theme->set_icon("close", "TabBar", make_icon(tab_close_png));
- theme->set_font("font", "Tabs", Ref<Font>());
- theme->set_font_size("font_size", "Tabs", -1);
+ theme->set_font("font", "TabBar", Ref<Font>());
+ theme->set_font_size("font_size", "TabBar", -1);
- theme->set_color("font_selected_color", "Tabs", control_font_hover_color);
- theme->set_color("font_unselected_color", "Tabs", control_font_low_color);
- theme->set_color("font_disabled_color", "Tabs", control_font_disabled_color);
- theme->set_color("font_outline_color", "Tabs", Color(1, 1, 1));
+ theme->set_color("font_selected_color", "TabBar", control_font_hover_color);
+ theme->set_color("font_unselected_color", "TabBar", control_font_low_color);
+ theme->set_color("font_disabled_color", "TabBar", control_font_disabled_color);
+ theme->set_color("font_outline_color", "TabBar", Color(1, 1, 1));
- theme->set_constant("hseparation", "Tabs", 4 * scale);
- theme->set_constant("outline_size", "Tabs", 0);
+ theme->set_constant("hseparation", "TabBar", 4 * scale);
+ theme->set_constant("outline_size", "TabBar", 0);
// Separators
@@ -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/mesh.h b/scene/resources/mesh.h
index 8d5571d67c..a95b4d4a5e 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -278,7 +278,6 @@ public:
int surface_get_array_index_len(int p_idx) const override;
uint32_t surface_get_format(int p_idx) const override;
PrimitiveType surface_get_primitive_type(int p_idx) const override;
- bool surface_is_alpha_sorting_enabled(int p_idx) const;
virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;
virtual Ref<Material> surface_get_material(int p_idx) const override;
diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h
index 14bdd60e4b..7c5d1344e8 100644
--- a/scene/resources/shape_2d.h
+++ b/scene/resources/shape_2d.h
@@ -64,7 +64,6 @@ public:
static bool is_collision_outline_enabled();
- Shape2D();
~Shape2D();
};
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/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h
index d5def670a4..398613aa44 100644
--- a/servers/audio/effects/audio_effect_limiter.h
+++ b/servers/audio/effects/audio_effect_limiter.h
@@ -72,8 +72,6 @@ public:
float get_soft_clip_ratio() const;
Ref<AudioEffectInstance> instantiate() override;
- void set_volume_db(float p_volume);
- float get_volume_db() const;
AudioEffectLimiter();
};
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 1a89821f80..6e862b1377 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -93,7 +93,6 @@ class AudioEffectRecord : public AudioEffect {
protected:
static void _bind_methods();
- static void debug(uint64_t time_diff, int p_frame_count);
public:
Ref<AudioEffectInstance> instantiate() override;
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index d01d1120bd..eaa66352f6 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -90,8 +90,6 @@ public:
float get_hpf() const;
Ref<AudioEffectInstance> instantiate() override;
- void set_volume_db(float p_volume);
- float get_volume_db() const;
AudioEffectReverb();
};
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 3897e5e7c2..3fb47e8f05 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -159,6 +159,14 @@ String DisplayServer::clipboard_get() const {
ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server.");
}
+void DisplayServer::clipboard_set_primary(const String &p_text) {
+ WARN_PRINT("Primary clipboard is not supported by this display server.");
+}
+
+String DisplayServer::clipboard_get_primary() const {
+ ERR_FAIL_V_MSG(String(), "Primary clipboard is not supported by this display server.");
+}
+
void DisplayServer::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) {
WARN_PRINT("Orientation not supported by this display server.");
}
@@ -360,6 +368,8 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set);
ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get);
+ ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary);
+ ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary);
ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count);
ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW));
@@ -487,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 f411a72aa3..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;
@@ -161,6 +162,8 @@ public:
virtual void clipboard_set(const String &p_text);
virtual String clipboard_get() const;
+ virtual void clipboard_set_primary(const String &p_text);
+ virtual String clipboard_get_primary() const;
enum {
SCREEN_OF_MAIN_WINDOW = -1
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp
index b0885a1f7b..56f191c203 100644
--- a/servers/physics_2d/godot_body_2d.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -55,7 +55,7 @@ void GodotBody2D::update_mass_properties() {
if (calculate_center_of_mass) {
// We have to recompute the center of mass.
- center_of_mass = Vector2();
+ center_of_mass_local = Vector2();
if (total_area != 0.0) {
for (int i = 0; i < get_shape_count(); i++) {
@@ -68,10 +68,10 @@ void GodotBody2D::update_mass_properties() {
real_t mass = area * this->mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass += mass * get_shape_transform(i).get_origin();
+ center_of_mass_local += mass * get_shape_transform(i).get_origin();
}
- center_of_mass /= mass;
+ center_of_mass_local /= mass;
}
}
@@ -94,7 +94,7 @@ void GodotBody2D::update_mass_properties() {
Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
- Vector2 shape_origin = mtx.get_origin() - center_of_mass;
+ Vector2 shape_origin = mtx.get_origin() - center_of_mass_local;
inertia += shape->get_moment_of_inertia(mass, scale) + mass * shape_origin.length_squared();
}
}
@@ -119,6 +119,8 @@ void GodotBody2D::update_mass_properties() {
} break;
}
+
+ _update_transform_dependent();
}
void GodotBody2D::reset_mass_properties() {
@@ -179,7 +181,8 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian
} break;
case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: {
calculate_center_of_mass = false;
- center_of_mass = p_value;
+ center_of_mass_local = p_value;
+ _update_transform_dependent();
} break;
case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: {
gravity_scale = p_value;
@@ -273,6 +276,7 @@ PhysicsServer2D::BodyMode GodotBody2D::get_mode() const {
void GodotBody2D::_shapes_changed() {
_mass_properties_changed();
+ wakeup();
wakeup_neighbours();
}
@@ -301,6 +305,7 @@ void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p
}
_set_transform(t);
_set_inv_transform(get_transform().inverse());
+ _update_transform_dependent();
}
wakeup();
@@ -400,6 +405,10 @@ void GodotBody2D::_compute_area_gravity_and_damping(const GodotArea2D *p_area) {
area_angular_damp += p_area->get_angular_damp();
}
+void GodotBody2D::_update_transform_dependent() {
+ center_of_mass = get_transform().basis_xform(center_of_mass_local);
+}
+
void GodotBody2D::integrate_forces(real_t p_step) {
if (mode == PhysicsServer2D::BODY_MODE_STATIC) {
return;
@@ -549,17 +558,13 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
real_t total_angular_velocity = angular_velocity + biased_angular_velocity;
Vector2 total_linear_velocity = linear_velocity + biased_linear_velocity;
- real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step;
+ real_t angle_delta = total_angular_velocity * p_step;
+ real_t angle = get_transform().get_rotation() + angle_delta;
Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;
- real_t center_of_mass_distance = center_of_mass.length();
- if (center_of_mass_distance > CMP_EPSILON) {
+ if (center_of_mass.length_squared() > CMP_EPSILON2) {
// Calculate displacement due to center of mass offset.
- real_t prev_angle = get_transform().get_rotation();
- real_t angle_base = Math::atan2(center_of_mass.y, center_of_mass.x);
- Vector2 point1(Math::cos(angle_base + prev_angle), Math::sin(angle_base + prev_angle));
- Vector2 point2(Math::cos(angle_base + angle), Math::sin(angle_base + angle));
- pos += center_of_mass_distance * (point1 - point2);
+ pos += center_of_mass - center_of_mass.rotated(angle_delta);
}
_set_transform(Transform2D(angle, pos), continuous_cd_mode == PhysicsServer2D::CCD_MODE_DISABLED);
@@ -568,6 +573,8 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) {
new_transform = get_transform();
}
+
+ _update_transform_dependent();
}
void GodotBody2D::wakeup_neighbours() {
diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h
index c4f3578f1b..5fce362fa7 100644
--- a/servers/physics_2d/godot_body_2d.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -66,6 +66,7 @@ class GodotBody2D : public GodotCollisionObject2D {
real_t inertia = 0.0;
real_t _inv_inertia = 0.0;
+ Vector2 center_of_mass_local;
Vector2 center_of_mass;
bool calculate_inertia = true;
@@ -139,7 +140,9 @@ class GodotBody2D : public GodotCollisionObject2D {
uint64_t island_step = 0;
- _FORCE_INLINE_ void _compute_area_gravity_and_damping(const GodotArea2D *p_area);
+ void _compute_area_gravity_and_damping(const GodotArea2D *p_area);
+
+ void _update_transform_dependent();
friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose
diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp
index 6df6a0c45b..02929eeaed 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -40,7 +40,7 @@ void GodotBody3D::_mass_properties_changed() {
}
}
-void GodotBody3D::_update_transform_dependant() {
+void GodotBody3D::_update_transform_dependent() {
center_of_mass = get_transform().basis.xform(center_of_mass_local);
principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;
@@ -161,7 +161,7 @@ void GodotBody3D::update_mass_properties() {
} break;
}
- _update_transform_dependant();
+ _update_transform_dependent();
}
void GodotBody3D::reset_mass_properties() {
@@ -217,14 +217,14 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian
if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
- _update_transform_dependant();
+ _update_transform_dependent();
}
}
} break;
case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: {
calculate_center_of_mass = false;
center_of_mass_local = p_value;
- _update_transform_dependant();
+ _update_transform_dependent();
} break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: {
gravity_scale = p_value;
@@ -295,7 +295,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && prev != mode) {
first_time_kinematic = true;
}
- _update_transform_dependant();
+ _update_transform_dependent();
} break;
case PhysicsServer3D::BODY_MODE_DYNAMIC: {
@@ -303,7 +303,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
if (!calculate_inertia) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
- _update_transform_dependant();
+ _update_transform_dependent();
}
_mass_properties_changed();
_set_static(false);
@@ -314,7 +314,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = Vector3();
angular_velocity = Vector3();
- _update_transform_dependant();
+ _update_transform_dependent();
_set_static(false);
set_active(true);
}
@@ -327,6 +327,8 @@ PhysicsServer3D::BodyMode GodotBody3D::get_mode() const {
void GodotBody3D::_shapes_changed() {
_mass_properties_changed();
+ wakeup();
+ wakeup_neighbours();
}
void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) {
@@ -355,6 +357,7 @@ void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p
}
_set_transform(t);
_set_inv_transform(get_transform().inverse());
+ _update_transform_dependent();
}
wakeup();
@@ -651,7 +654,7 @@ void GodotBody3D::integrate_velocities(real_t p_step) {
_set_transform(transform);
_set_inv_transform(get_transform().inverse());
- _update_transform_dependant();
+ _update_transform_dependent();
}
void GodotBody3D::wakeup_neighbours() {
diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h
index 1151a22c96..5acdab9d13 100644
--- a/servers/physics_3d/godot_body_3d.h
+++ b/servers/physics_3d/godot_body_3d.h
@@ -135,9 +135,9 @@ class GodotBody3D : public GodotCollisionObject3D {
uint64_t island_step = 0;
- _FORCE_INLINE_ void _compute_area_gravity_and_damping(const GodotArea3D *p_area);
+ void _compute_area_gravity_and_damping(const GodotArea3D *p_area);
- _FORCE_INLINE_ void _update_transform_dependant();
+ void _update_transform_dependent();
friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index 34b56e733e..79a2e0b0ea 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -584,7 +584,6 @@ void GodotPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer
ERR_FAIL_COND(!body);
body->set_collision_layer(p_layer);
- body->wakeup();
}
uint32_t GodotPhysicsServer3D::body_get_collision_layer(RID p_body) const {
@@ -599,7 +598,6 @@ void GodotPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask)
ERR_FAIL_COND(!body);
body->set_collision_mask(p_mask);
- body->wakeup();
}
uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const {
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index d15235d27c..f214e3603a 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -139,6 +139,7 @@ void GodotSoftBody3D::set_mesh(RID p_mesh) {
}
Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0);
+ ERR_FAIL_COND(arrays.is_empty());
bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]);
if (!success) {
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
index d7e0537439..b88e2d1190 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
@@ -232,7 +232,7 @@ GodotGeneric6DOFJoint3D::GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *
void GodotGeneric6DOFJoint3D::calculateAngleInfo() {
Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis;
- m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz();
+ m_calculatedAxisAngleDiff = relative_frame.get_euler(Basis::EULER_ORDER_XYZ);
// in euler angle mode we do not actually constrain the angular velocity
// along the axes axis[0] and axis[2] (although we do use axis[1]) :
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index 927ef5d57c..4a2f07ab1e 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -59,9 +59,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
bool create_thread = false;
Semaphore step_sem;
- int step_pending = 0;
void thread_step(real_t p_delta);
- void thread_flush();
void thread_exit();
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index bf936fd0fc..4c88ef2642 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -58,9 +58,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D {
bool create_thread = false;
Semaphore step_sem;
- int step_pending = 0;
void thread_step(real_t p_delta);
- void thread_flush();
void thread_exit();
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index a1c3481ed6..d05cfdc386 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -657,6 +657,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
}
+ actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps
+ actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]";
+ actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter
+
actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index d128578d0b..a906a853dc 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -2696,9 +2696,14 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
switch (shadows_quality) {
case RS::SHADOW_QUALITY_HARD: {
penumbra_shadow_samples = 4;
- soft_shadow_samples = 1;
+ soft_shadow_samples = 0;
shadows_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ penumbra_shadow_samples = 4;
+ soft_shadow_samples = 1;
+ shadows_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
penumbra_shadow_samples = 8;
soft_shadow_samples = 4;
@@ -2738,9 +2743,14 @@ void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_q
switch (directional_shadow_quality) {
case RS::SHADOW_QUALITY_HARD: {
directional_penumbra_shadow_samples = 4;
- directional_soft_shadow_samples = 1;
+ directional_soft_shadow_samples = 0;
directional_shadow_quality_radius = 1.0;
} break;
+ case RS::SHADOW_QUALITY_SOFT_VERY_LOW: {
+ directional_penumbra_shadow_samples = 4;
+ directional_soft_shadow_samples = 1;
+ directional_shadow_quality_radius = 1.5;
+ } break;
case RS::SHADOW_QUALITY_SOFT_LOW: {
directional_penumbra_shadow_samples = 8;
directional_soft_shadow_samples = 4;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index a7bfea455d..3e68a2b622 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -2672,9 +2672,11 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari
if (uniform_array_size > 0) {
if (textures.size() < uniform_array_size) {
const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name);
- if (W) {
- for (int j = textures.size(); j < uniform_array_size; j++) {
+ for (int j = textures.size(); j < uniform_array_size; j++) {
+ if (W) {
textures.push_back(W->get());
+ } else {
+ textures.push_back(RID());
}
}
}
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 4d466342f8..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
@@ -301,7 +301,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_directional_soft_shadow_samples == 1) {
+ if (sc_directional_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -327,7 +327,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float depth = coord.z;
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
}
@@ -350,7 +350,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) {
float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec4 uv_rect, vec2 flip_offset, float depth) {
//if only one sample is taken, take it from the center
- if (sc_soft_shadow_samples == 1) {
+ if (sc_soft_shadow_samples == 0) {
vec2 pos = coord * 0.5 + 0.5;
pos = uv_rect.xy + pos * uv_rect.zw;
return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0));
@@ -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) {
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 9c38bf7606..53f2d96f52 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -2763,6 +2763,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
bool is_const = false;
ConstantNode::Value value;
+ value.sint = -1;
_find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value);
if (!is_const || value.sint < min || value.sint > max) {
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index b3efe840b6..039dbc71e3 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1942,6 +1942,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
+ BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_VERY_LOW);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_LOW);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_MEDIUM);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_SOFT_HIGH);
@@ -2793,14 +2794,14 @@ RenderingServer::RenderingServer() {
GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096);
GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 3);
GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2);
+ GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 3);
GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
@@ -2810,6 +2811,12 @@ RenderingServer::RenderingServer() {
PropertyInfo(Variant::INT,
"rendering/vulkan/rendering/back_end",
PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)"));
+ // Already defined in RenderingDeviceVulkan::initialize which runs before this code.
+ // We re-define them here just for doctool's sake. Make sure to keep default values in sync.
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256);
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128);
+ GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64);
+ GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64);
GLOBAL_DEF("rendering/3d/viewport/scale", 1.0);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale",
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index b50da66d03..b6068afcf1 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -474,6 +474,7 @@ public:
enum ShadowQuality {
SHADOW_QUALITY_HARD,
+ SHADOW_QUALITY_SOFT_VERY_LOW,
SHADOW_QUALITY_SOFT_LOW,
SHADOW_QUALITY_SOFT_MEDIUM,
SHADOW_QUALITY_SOFT_HIGH,
diff --git a/tests/test_basis.h b/tests/test_basis.h
index 11c68f9eb7..b254d9fb7f 100644
--- a/tests/test_basis.h
+++ b/tests/test_basis.h
@@ -60,27 +60,27 @@ Basis EulerToBasis(RotOrder mode, const Vector3 &p_rotation) {
Basis ret;
switch (mode) {
case EulerXYZ:
- ret.set_euler_xyz(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_XYZ);
break;
case EulerXZY:
- ret.set_euler_xzy(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_XZY);
break;
case EulerYZX:
- ret.set_euler_yzx(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_YZX);
break;
case EulerYXZ:
- ret.set_euler_yxz(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_YXZ);
break;
case EulerZXY:
- ret.set_euler_zxy(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_ZXY);
break;
case EulerZYX:
- ret.set_euler_zyx(p_rotation);
+ ret.set_euler(p_rotation, Basis::EULER_ORDER_ZYX);
break;
default:
@@ -94,22 +94,22 @@ Basis EulerToBasis(RotOrder mode, const Vector3 &p_rotation) {
Vector3 BasisToEuler(RotOrder mode, const Basis &p_rotation) {
switch (mode) {
case EulerXYZ:
- return p_rotation.get_euler_xyz();
+ return p_rotation.get_euler(Basis::EULER_ORDER_XYZ);
case EulerXZY:
- return p_rotation.get_euler_xzy();
+ return p_rotation.get_euler(Basis::EULER_ORDER_XZY);
case EulerYZX:
- return p_rotation.get_euler_yzx();
+ return p_rotation.get_euler(Basis::EULER_ORDER_YZX);
case EulerYXZ:
- return p_rotation.get_euler_yxz();
+ return p_rotation.get_euler(Basis::EULER_ORDER_YXZ);
case EulerZXY:
- return p_rotation.get_euler_zxy();
+ return p_rotation.get_euler(Basis::EULER_ORDER_ZXY);
case EulerZYX:
- return p_rotation.get_euler_zyx();
+ return p_rotation.get_euler(Basis::EULER_ORDER_ZYX);
default:
// If you land here, Please integrate all rotation orders.
@@ -170,9 +170,9 @@ void test_rotation(Vector3 deg_original_euler, RotOrder rot_order) {
CHECK_MESSAGE((res.get_axis(2) - Vector3(0.0, 0.0, 1.0)).length() <= 0.1, vformat("Fail due to Z %s\n", String(res.get_axis(2))).utf8().ptr());
// Double check `to_rotation` decomposing with XYZ rotation order.
- const Vector3 euler_xyz_from_rotation = to_rotation.get_euler_xyz();
+ const Vector3 euler_xyz_from_rotation = to_rotation.get_euler(Basis::EULER_ORDER_XYZ);
Basis rotation_from_xyz_computed_euler;
- rotation_from_xyz_computed_euler.set_euler_xyz(euler_xyz_from_rotation);
+ rotation_from_xyz_computed_euler.set_euler(euler_xyz_from_rotation, Basis::EULER_ORDER_XYZ);
res = to_rotation.inverse() * rotation_from_xyz_computed_euler;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 964ac6246e..319e4d1ee0 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -318,6 +318,9 @@ File extracted from upstream release tarball:
pre-defined symbol.
- Applied the patch in `patches/pr4948-fix-clang12-opt.patch`. Upstream bugfix
from PR 4948 to fix a bug caused by Clang 12 optimizations.
+- Applied the patch in `patches/pr4819-faster-base64.patch`. This fixes a certs
+ parsing speed regression since 2.16.10 (upstream PR:
+ https://github.com/ARMmbed/mbedtls/pull/4819).
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
providing configuration for light bundling with core.
diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c
index 692e11e3fa..b89313062b 100644
--- a/thirdparty/mbedtls/library/base64.c
+++ b/thirdparty/mbedtls/library/base64.c
@@ -66,127 +66,38 @@
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
-static const unsigned char base64_enc_map[64] =
-{
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '+', '/'
-};
-
-static const unsigned char base64_dec_map[128] =
-{
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
- 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 127, 127, 127, 127, 127
-};
-
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
-/*
- * Constant flow conditional assignment to unsigned char
- */
-static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
- unsigned char condition )
-{
- /* MSVC has a warning about unary minus on unsigned integer types,
- * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
- /* Generate bitmask from condition, mask will either be 0xFF or 0 */
- unsigned char mask = ( condition | -condition );
- mask >>= 7;
- mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
- *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
-}
-
-/*
- * Constant flow conditional assignment to uint_32
- */
-static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
- uint32_t condition )
-{
- /* MSVC has a warning about unary minus on unsigned integer types,
- * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
- /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
- uint32_t mask = ( condition | -condition );
- mask >>= 31;
- mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
- *dest = ( src & mask ) | ( ( *dest ) & ~mask );
-}
-
-/*
- * Constant flow check for equality
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
*/
-static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
+static unsigned char mask_of_range( unsigned char low, unsigned char high,
+ unsigned char c )
{
- size_t difference = in_a ^ in_b;
-
- /* MSVC has a warning about unary minus on unsigned integer types,
- * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
- difference |= -difference;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
- /* cope with the varying size of size_t per platform */
- difference >>= ( sizeof( difference ) * 8 - 1 );
-
- return (unsigned char) ( 1 ^ difference );
+ /* low_mask is: 0 if low <= c, 0x...ff if low > c */
+ unsigned low_mask = ( (unsigned) c - low ) >> 8;
+ /* high_mask is: 0 if c <= high, 0x...ff if high > c */
+ unsigned high_mask = ( (unsigned) high - c ) >> 8;
+ return( ~( low_mask | high_mask ) & 0xff );
}
-/*
- * Constant flow lookup into table.
+/* Given a value in the range 0..63, return the corresponding Base64 digit.
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
*/
-static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
- const size_t table_size, const size_t table_index )
+static unsigned char enc_char( unsigned char val )
{
- size_t i;
- unsigned char result = 0;
-
- for( i = 0; i < table_size; ++i )
- {
- mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
- }
-
- return result;
+ unsigned char digit = 0;
+ /* For each range of values, if val is in that range, mask digit with
+ * the corresponding value. Since val can only be in a single range,
+ * only at most one masking will change digit. */
+ digit |= mask_of_range( 0, 25, val ) & ( 'A' + val );
+ digit |= mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
+ digit |= mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
+ digit |= mask_of_range( 62, 62, val ) & '+';
+ digit |= mask_of_range( 63, 63, val ) & '/';
+ return( digit );
}
/*
@@ -229,17 +140,10 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C2 = *src++;
C3 = *src++;
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( C1 >> 2 ) & 0x3F ) );
-
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
-
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
-
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( C3 & 0x3F ) );
+ *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
+ *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
+ *p++ = enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F );
+ *p++ = enc_char( C3 & 0x3F );
}
if( i < slen )
@@ -247,15 +151,11 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
C1 = *src++;
C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( C1 >> 2 ) & 0x3F ) );
-
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+ *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
+ *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
if( ( i + 1 ) < slen )
- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
- ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
+ *p++ = enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
else *p++ = '=';
*p++ = '=';
@@ -267,26 +167,57 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
return( 0 );
}
+/* Given a Base64 digit, return its value.
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * The implementation is constant-flow (no branch or memory access depending
+ * on the value of c) unless the compiler inlines and optimizes a specific
+ * access.
+ */
+static signed char dec_value( unsigned char c )
+{
+ unsigned char val = 0;
+ /* For each range of digits, if c is in that range, mask val with
+ * the corresponding value. Since c can only be in a single range,
+ * only at most one masking will change val. Set val to one plus
+ * the desired value so that it stays 0 if c is in none of the ranges. */
+ val |= mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
+ val |= mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
+ val |= mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
+ val |= mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
+ val |= mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+ /* At this point, val is 0 if c is an invalid digit and v+1 if c is
+ * a digit with the value v. */
+ return( val - 1 );
+}
+
/*
* Decode a base64-formatted buffer
*/
int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen )
{
- size_t i, n;
- uint32_t j, x;
+ size_t i; /* index in source */
+ size_t n; /* number of digits or trailing = in source */
+ uint32_t x; /* value accumulator */
+ unsigned accumulated_digits = 0;
+ unsigned equals = 0;
+ int spaces_present = 0;
unsigned char *p;
- unsigned char dec_map_lookup;
/* First pass: check for validity and get output length */
- for( i = n = j = 0; i < slen; i++ )
+ for( i = n = 0; i < slen; i++ )
{
/* Skip spaces before checking for EOL */
- x = 0;
+ spaces_present = 0;
while( i < slen && src[i] == ' ' )
{
++i;
- ++x;
+ spaces_present = 1;
}
/* Spaces at end of buffer are OK */
@@ -301,20 +232,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
continue;
/* Space inside a line is an error */
- if( x != 0 )
+ if( spaces_present )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
- if( src[i] == '=' && ++j > 2 )
- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
- dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
-
- if( src[i] > 127 || dec_map_lookup == 127 )
- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
- if( dec_map_lookup < 64 && j != 0 )
+ if( src[i] > 127 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+ if( src[i] == '=' )
+ {
+ if( ++equals > 2 )
+ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+ }
+ else
+ {
+ if( equals != 0 )
+ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+ if( dec_value( src[i] ) < 0 )
+ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+ }
n++;
}
@@ -329,7 +264,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
* n = ( ( n * 6 ) + 7 ) >> 3;
*/
n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
- n -= j;
+ n -= equals;
if( dst == NULL || dlen < n )
{
@@ -337,22 +272,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
}
- for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
- {
+ equals = 0;
+ for( x = 0, p = dst; i > 0; i--, src++ )
+ {
if( *src == '\r' || *src == '\n' || *src == ' ' )
continue;
- dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
-
- mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
- x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
+ x = x << 6;
+ if( *src == '=' )
+ ++equals;
+ else
+ x |= dec_value( *src );
- if( ++n == 4 )
+ if( ++accumulated_digits == 4 )
{
- n = 0;
- if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
- if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
- if( j > 2 ) *p++ = (unsigned char)( x );
+ accumulated_digits = 0;
+ *p++ = (unsigned char)( x >> 16 );
+ if( equals <= 1 ) *p++ = (unsigned char)( x >> 8 );
+ if( equals <= 0 ) *p++ = (unsigned char)( x );
}
}
diff --git a/thirdparty/mbedtls/patches/pr4819-faster-base64.patch b/thirdparty/mbedtls/patches/pr4819-faster-base64.patch
new file mode 100644
index 0000000000..2f25b7b54c
--- /dev/null
+++ b/thirdparty/mbedtls/patches/pr4819-faster-base64.patch
@@ -0,0 +1,341 @@
+diff --git a/library/base64.c b/library/base64.c
+index 692e11e3fae..b89313062b6 100644
+--- a/library/base64.c
++++ b/library/base64.c
+@@ -66,127 +66,38 @@
+ #endif /* MBEDTLS_PLATFORM_C */
+ #endif /* MBEDTLS_SELF_TEST */
+
+-static const unsigned char base64_enc_map[64] =
+-{
+- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+- 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+- 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+- 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+- '8', '9', '+', '/'
+-};
+-
+-static const unsigned char base64_dec_map[128] =
+-{
+- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
+- 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
+- 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
+- 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
+- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+- 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
+- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+- 49, 50, 51, 127, 127, 127, 127, 127
+-};
+-
+ #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
+
+-/*
+- * Constant flow conditional assignment to unsigned char
+- */
+-static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
+- unsigned char condition )
+-{
+- /* MSVC has a warning about unary minus on unsigned integer types,
+- * but this is well-defined and precisely what we want to do here. */
+-#if defined(_MSC_VER)
+-#pragma warning( push )
+-#pragma warning( disable : 4146 )
+-#endif
+-
+- /* Generate bitmask from condition, mask will either be 0xFF or 0 */
+- unsigned char mask = ( condition | -condition );
+- mask >>= 7;
+- mask = -mask;
+-
+-#if defined(_MSC_VER)
+-#pragma warning( pop )
+-#endif
+-
+- *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
+-}
+-
+-/*
+- * Constant flow conditional assignment to uint_32
+- */
+-static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
+- uint32_t condition )
+-{
+- /* MSVC has a warning about unary minus on unsigned integer types,
+- * but this is well-defined and precisely what we want to do here. */
+-#if defined(_MSC_VER)
+-#pragma warning( push )
+-#pragma warning( disable : 4146 )
+-#endif
+-
+- /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
+- uint32_t mask = ( condition | -condition );
+- mask >>= 31;
+- mask = -mask;
+-
+-#if defined(_MSC_VER)
+-#pragma warning( pop )
+-#endif
+-
+- *dest = ( src & mask ) | ( ( *dest ) & ~mask );
+-}
+-
+-/*
+- * Constant flow check for equality
++/* Return 0xff if low <= c <= high, 0 otherwise.
++ *
++ * Constant flow with respect to c.
+ */
+-static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
++static unsigned char mask_of_range( unsigned char low, unsigned char high,
++ unsigned char c )
+ {
+- size_t difference = in_a ^ in_b;
+-
+- /* MSVC has a warning about unary minus on unsigned integer types,
+- * but this is well-defined and precisely what we want to do here. */
+-#if defined(_MSC_VER)
+-#pragma warning( push )
+-#pragma warning( disable : 4146 )
+-#endif
+-
+- difference |= -difference;
+-
+-#if defined(_MSC_VER)
+-#pragma warning( pop )
+-#endif
+-
+- /* cope with the varying size of size_t per platform */
+- difference >>= ( sizeof( difference ) * 8 - 1 );
+-
+- return (unsigned char) ( 1 ^ difference );
++ /* low_mask is: 0 if low <= c, 0x...ff if low > c */
++ unsigned low_mask = ( (unsigned) c - low ) >> 8;
++ /* high_mask is: 0 if c <= high, 0x...ff if high > c */
++ unsigned high_mask = ( (unsigned) high - c ) >> 8;
++ return( ~( low_mask | high_mask ) & 0xff );
+ }
+
+-/*
+- * Constant flow lookup into table.
++/* Given a value in the range 0..63, return the corresponding Base64 digit.
++ * The implementation assumes that letters are consecutive (e.g. ASCII
++ * but not EBCDIC).
+ */
+-static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
+- const size_t table_size, const size_t table_index )
++static unsigned char enc_char( unsigned char val )
+ {
+- size_t i;
+- unsigned char result = 0;
+-
+- for( i = 0; i < table_size; ++i )
+- {
+- mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
+- }
+-
+- return result;
++ unsigned char digit = 0;
++ /* For each range of values, if val is in that range, mask digit with
++ * the corresponding value. Since val can only be in a single range,
++ * only at most one masking will change digit. */
++ digit |= mask_of_range( 0, 25, val ) & ( 'A' + val );
++ digit |= mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
++ digit |= mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
++ digit |= mask_of_range( 62, 62, val ) & '+';
++ digit |= mask_of_range( 63, 63, val ) & '/';
++ return( digit );
+ }
+
+ /*
+@@ -229,17 +140,10 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+ C2 = *src++;
+ C3 = *src++;
+
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( C1 >> 2 ) & 0x3F ) );
+-
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+-
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
+-
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( C3 & 0x3F ) );
++ *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
++ *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
++ *p++ = enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F );
++ *p++ = enc_char( C3 & 0x3F );
+ }
+
+ if( i < slen )
+@@ -247,15 +151,11 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+ C1 = *src++;
+ C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
+
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( C1 >> 2 ) & 0x3F ) );
+-
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
++ *p++ = enc_char( ( C1 >> 2 ) & 0x3F );
++ *p++ = enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F );
+
+ if( ( i + 1 ) < slen )
+- *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
+- ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
++ *p++ = enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
+ else *p++ = '=';
+
+ *p++ = '=';
+@@ -267,26 +167,57 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
+ return( 0 );
+ }
+
++/* Given a Base64 digit, return its value.
++ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
++ * return -1.
++ *
++ * The implementation assumes that letters are consecutive (e.g. ASCII
++ * but not EBCDIC).
++ *
++ * The implementation is constant-flow (no branch or memory access depending
++ * on the value of c) unless the compiler inlines and optimizes a specific
++ * access.
++ */
++static signed char dec_value( unsigned char c )
++{
++ unsigned char val = 0;
++ /* For each range of digits, if c is in that range, mask val with
++ * the corresponding value. Since c can only be in a single range,
++ * only at most one masking will change val. Set val to one plus
++ * the desired value so that it stays 0 if c is in none of the ranges. */
++ val |= mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 );
++ val |= mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
++ val |= mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
++ val |= mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
++ val |= mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
++ /* At this point, val is 0 if c is an invalid digit and v+1 if c is
++ * a digit with the value v. */
++ return( val - 1 );
++}
++
+ /*
+ * Decode a base64-formatted buffer
+ */
+ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ const unsigned char *src, size_t slen )
+ {
+- size_t i, n;
+- uint32_t j, x;
++ size_t i; /* index in source */
++ size_t n; /* number of digits or trailing = in source */
++ uint32_t x; /* value accumulator */
++ unsigned accumulated_digits = 0;
++ unsigned equals = 0;
++ int spaces_present = 0;
+ unsigned char *p;
+- unsigned char dec_map_lookup;
+
+ /* First pass: check for validity and get output length */
+- for( i = n = j = 0; i < slen; i++ )
++ for( i = n = 0; i < slen; i++ )
+ {
+ /* Skip spaces before checking for EOL */
+- x = 0;
++ spaces_present = 0;
+ while( i < slen && src[i] == ' ' )
+ {
+ ++i;
+- ++x;
++ spaces_present = 1;
+ }
+
+ /* Spaces at end of buffer are OK */
+@@ -301,20 +232,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ continue;
+
+ /* Space inside a line is an error */
+- if( x != 0 )
++ if( spaces_present )
+ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
+- if( src[i] == '=' && ++j > 2 )
+- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+-
+- dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
+-
+- if( src[i] > 127 || dec_map_lookup == 127 )
+- return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+-
+- if( dec_map_lookup < 64 && j != 0 )
++ if( src[i] > 127 )
+ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+
++ if( src[i] == '=' )
++ {
++ if( ++equals > 2 )
++ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
++ }
++ else
++ {
++ if( equals != 0 )
++ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
++ if( dec_value( src[i] ) < 0 )
++ return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
++ }
+ n++;
+ }
+
+@@ -329,7 +264,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ * n = ( ( n * 6 ) + 7 ) >> 3;
+ */
+ n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
+- n -= j;
++ n -= equals;
+
+ if( dst == NULL || dlen < n )
+ {
+@@ -337,22 +272,24 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
+ return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
+ }
+
+- for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
+- {
++ equals = 0;
++ for( x = 0, p = dst; i > 0; i--, src++ )
++ {
+ if( *src == '\r' || *src == '\n' || *src == ' ' )
+ continue;
+
+- dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
+-
+- mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
+- x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
++ x = x << 6;
++ if( *src == '=' )
++ ++equals;
++ else
++ x |= dec_value( *src );
+
+- if( ++n == 4 )
++ if( ++accumulated_digits == 4 )
+ {
+- n = 0;
+- if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
+- if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
+- if( j > 2 ) *p++ = (unsigned char)( x );
++ accumulated_digits = 0;
++ *p++ = (unsigned char)( x >> 16 );
++ if( equals <= 1 ) *p++ = (unsigned char)( x >> 8 );
++ if( equals <= 0 ) *p++ = (unsigned char)( x );
+ }
+ }
+